--- /dev/null
+#include "AES.h"
+
+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+ 1. source code distributions include the above copyright notice, this
+ list of conditions and the following disclaimer;
+
+ 2. binary distributions include the above copyright notice, this list
+ of conditions and the following disclaimer in their documentation;
+
+ 3. the name of the copyright holder is not used to endorse products
+ built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue 09/09/2006
+
+ This is an AES implementation that uses only 8-bit byte operations on the
+ cipher state (there are options to use 32-bit types if available).
+
+ The combination of mix columns and byte substitution used here is based on
+ that developed by Karl Malbrain. His contribution is acknowledged.
+ */
+
+/* This version derived by Mark Tillotson 2012-01-23, tidied up, slimmed down
+ and tailored to 8-bit microcontroller abilities and Arduino datatypes.
+
+ The s-box and inverse s-box were retained as tables (0.5kB PROGMEM) but all
+ the other transformations are coded to save table space. Many efficiency
+ improvments to the routines mix_sub_columns() and inv_mix_sub_columns()
+ (mainly common sub-expression elimination).
+
+ Only the routines with precalculated subkey schedule are retained (together
+ with set_key() - this does however mean each AES object takes 240 bytes of
+ RAM, alas)
+
+ The CBC routines side-effect the iv argument (so that successive calls work
+ together correctly).
+
+ All the encryption and decryption routines work with plain == cipher for
+ in-place encryption, note.
+
+*/
+
+
+/* functions for finite field multiplication in the AES Galois field */
+
+/* code was modified by george spanos <spaniakos@gmail.com>
+ * 16/12/14
+ */
+
+// GF(2^8) stuff
+
+#define WPOLY 0x011B
+#define DPOLY 0x008D
+
+static const byte s_fwd [0x100] PROGMEM =
+{
+ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
+ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
+ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
+ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
+} ;
+
+static const byte s_inv [0x100] PROGMEM =
+{
+ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
+ 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
+ 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
+ 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
+ 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
+ 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
+ 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
+ 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
+ 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
+ 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
+ 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
+ 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
+ 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
+ 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
+ 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
+} ;
+
+// times 2 in the GF(2^8)
+#define f2(x) ((x) & 0x80 ? (x << 1) ^ WPOLY : x << 1)
+#define d2(x) (((x) >> 1) ^ ((x) & 1 ? DPOLY : 0))
+
+static byte s_box (byte x)
+{
+ // return fwd_affine (pgm_read_byte (&inv [x])) ;
+ return pgm_read_byte (& s_fwd [x]) ;
+}
+
+// Inverse Sbox
+static byte is_box (byte x)
+{
+ // return pgm_read_byte (&inv [inv_affine (x)]) ;
+ return pgm_read_byte (& s_inv [x]) ;
+}
+
+
+static void xor_block (byte * d, byte * s)
+{
+ for (byte i = 0 ; i < N_BLOCK ; i += 4)
+ {
+ *d++ ^= *s++ ; // some unrolling
+ *d++ ^= *s++ ;
+ *d++ ^= *s++ ;
+ *d++ ^= *s++ ;
+ }
+}
+
+static void copy_and_key (byte * d, byte * s, byte * k)
+{
+ for (byte i = 0 ; i < N_BLOCK ; i += 4)
+ {
+ *d++ = *s++ ^ *k++ ; // some unrolling
+ *d++ = *s++ ^ *k++ ;
+ *d++ = *s++ ^ *k++ ;
+ *d++ = *s++ ^ *k++ ;
+ }
+}
+
+// #define add_round_key(d, k) xor_block (d, k)
+
+/* SUB ROW PHASE */
+
+static void shift_sub_rows (byte st [N_BLOCK])
+{
+ st [0] = s_box (st [0]) ; st [4] = s_box (st [4]) ;
+ st [8] = s_box (st [8]) ; st [12] = s_box (st [12]) ;
+
+ byte tt = st [1] ;
+ st [1] = s_box (st [5]) ; st [5] = s_box (st [9]) ;
+ st [9] = s_box (st [13]) ; st [13] = s_box (tt) ;
+
+ tt = st[2] ; st [2] = s_box (st [10]) ; st [10] = s_box (tt) ;
+ tt = st[6] ; st [6] = s_box (st [14]) ; st [14] = s_box (tt) ;
+
+ tt = st[15] ;
+ st [15] = s_box (st [11]) ; st [11] = s_box (st [7]) ;
+ st [7] = s_box (st [3]) ; st [3] = s_box (tt) ;
+}
+
+static void inv_shift_sub_rows (byte st[N_BLOCK])
+{
+ st [0] = is_box (st[0]) ; st [4] = is_box (st [4]);
+ st [8] = is_box (st[8]) ; st [12] = is_box (st [12]);
+
+ byte tt = st[13] ;
+ st [13] = is_box (st [9]) ; st [9] = is_box (st [5]) ;
+ st [5] = is_box (st [1]) ; st [1] = is_box (tt) ;
+
+ tt = st [2] ; st [2] = is_box (st [10]) ; st [10] = is_box (tt) ;
+ tt = st [6] ; st [6] = is_box (st [14]) ; st [14] = is_box (tt) ;
+
+ tt = st [3] ;
+ st [3] = is_box (st [7]) ; st [7] = is_box (st [11]) ;
+ st [11] = is_box (st [15]) ; st [15] = is_box (tt) ;
+}
+
+/* SUB COLUMNS PHASE */
+
+static void mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK])
+{
+ byte j = 5 ;
+ byte k = 10 ;
+ byte l = 15 ;
+ for (byte i = 0 ; i < N_BLOCK ; i += N_COL)
+ {
+ byte a = st [i] ;
+ byte b = st [j] ; j = (j+N_COL) & 15 ;
+ byte c = st [k] ; k = (k+N_COL) & 15 ;
+ byte d = st [l] ; l = (l+N_COL) & 15 ;
+ byte a1 = s_box (a), b1 = s_box (b), c1 = s_box (c), d1 = s_box (d) ;
+ byte a2 = f2(a1), b2 = f2(b1), c2 = f2(c1), d2 = f2(d1) ;
+ dt[i] = a2 ^ b2^b1 ^ c1 ^ d1 ;
+ dt[i+1] = a1 ^ b2 ^ c2^c1 ^ d1 ;
+ dt[i+2] = a1 ^ b1 ^ c2 ^ d2^d1 ;
+ dt[i+3] = a2^a1 ^ b1 ^ c1 ^ d2 ;
+ }
+}
+
+static void inv_mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK])
+{
+ for (byte i = 0 ; i < N_BLOCK ; i += N_COL)
+ {
+ byte a1 = st [i] ;
+ byte b1 = st [i+1] ;
+ byte c1 = st [i+2] ;
+ byte d1 = st [i+3] ;
+ byte a2 = f2(a1), b2 = f2(b1), c2 = f2(c1), d2 = f2(d1) ;
+ byte a4 = f2(a2), b4 = f2(b2), c4 = f2(c2), d4 = f2(d2) ;
+ byte a8 = f2(a4), b8 = f2(b4), c8 = f2(c4), d8 = f2(d4) ;
+ byte a9 = a8 ^ a1,b9 = b8 ^ b1,c9 = c8 ^ c1,d9 = d8 ^ d1 ;
+ byte ac = a8 ^ a4,bc = b8 ^ b4,cc = c8 ^ c4,dc = d8 ^ d4 ;
+
+ dt[i] = is_box (ac^a2 ^ b9^b2 ^ cc^c1 ^ d9) ;
+ dt[(i+5)&15] = is_box (a9 ^ bc^b2 ^ c9^c2 ^ dc^d1) ;
+ dt[(i+10)&15] = is_box (ac^a1 ^ b9 ^ cc^c2 ^ d9^d2) ;
+ dt[(i+15)&15] = is_box (a9^a2 ^ bc^b1 ^ c9 ^ dc^d2) ;
+ }
+}
+
+/******************************************************************************/
+
+AES::AES(){
+ byte ar_iv[8] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 };
+ memcpy(iv,ar_iv,8);
+ memcpy(iv+8,ar_iv,8);
+ arr_pad[0] = 0x01;
+ arr_pad[1] = 0x02;
+ arr_pad[2] = 0x03;
+ arr_pad[3] = 0x04;
+ arr_pad[4] = 0x05;
+ arr_pad[5] = 0x06;
+ arr_pad[6] = 0x07;
+ arr_pad[7] = 0x08;
+ arr_pad[8] = 0x09;
+ arr_pad[9] = 0x0a;
+ arr_pad[10] = 0x0b;
+ arr_pad[11] = 0x0c;
+ arr_pad[12] = 0x0d;
+ arr_pad[13] = 0x0e;
+ arr_pad[14] = 0x0f;
+}
+
+/******************************************************************************/
+
+byte AES::set_key (byte key [], int keylen)
+{
+ byte hi ;
+ switch (keylen)
+ {
+ case 16:
+ case 128:
+ keylen = 16; // 10 rounds
+ round = 10 ;
+ break;
+ case 24:
+ case 192:
+ keylen = 24; // 12 rounds
+ round = 12 ;
+ break;
+ case 32:
+ case 256:
+ keylen = 32; // 14 rounds
+ round = 14 ;
+ break;
+ default:
+ round = 0;
+ return FAILURE;
+ }
+ hi = (round + 1) << 4 ;
+ copy_n_bytes (key_sched, key, keylen) ;
+ byte t[4] ;
+ byte next = keylen ;
+ for (byte cc = keylen, rc = 1 ; cc < hi ; cc += N_COL)
+ {
+ for (byte i = 0 ; i < N_COL ; i++)
+ t[i] = key_sched [cc-4+i] ;
+ if (cc == next)
+ {
+ next += keylen ;
+ byte ttt = t[0] ;
+ t[0] = s_box (t[1]) ^ rc ;
+ t[1] = s_box (t[2]) ;
+ t[2] = s_box (t[3]) ;
+ t[3] = s_box (ttt) ;
+ rc = f2 (rc) ;
+ }
+ else if (keylen == 32 && (cc & 31) == 16)
+ {
+ for (byte i = 0 ; i < 4 ; i++)
+ t[i] = s_box (t[i]) ;
+ }
+ byte tt = cc - keylen ;
+ for (byte i = 0 ; i < N_COL ; i++)
+ key_sched [cc + i] = key_sched [tt + i] ^ t[i] ;
+ }
+ return SUCCESS ;
+}
+
+/******************************************************************************/
+
+void AES::clean ()
+{
+ for (byte i = 0 ; i < KEY_SCHEDULE_BYTES ; i++)
+ key_sched [i] = 0 ;
+ round = 0 ;
+}
+
+/******************************************************************************/
+
+void AES::copy_n_bytes (byte * d, byte * s, byte nn)
+{
+ while (nn >= 4)
+ {
+ *d++ = *s++ ; // some unrolling
+ *d++ = *s++ ;
+ *d++ = *s++ ;
+ *d++ = *s++ ;
+ nn -= 4 ;
+ }
+ while (nn--)
+ *d++ = *s++ ;
+}
+
+/******************************************************************************/
+
+byte AES::encrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK])
+{
+ if (round)
+ {
+ byte s1 [N_BLOCK], r ;
+ copy_and_key (s1, plain, (byte*) (key_sched)) ;
+
+ for (r = 1 ; r < round ; r++)
+ {
+ byte s2 [N_BLOCK] ;
+ mix_sub_columns (s2, s1) ;
+ copy_and_key (s1, s2, (byte*) (key_sched + r * N_BLOCK)) ;
+ }
+ shift_sub_rows (s1) ;
+ copy_and_key (cipher, s1, (byte*) (key_sched + r * N_BLOCK)) ;
+ }
+ else
+ return FAILURE ;
+ return SUCCESS ;
+}
+
+/******************************************************************************/
+
+byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block, byte iv [N_BLOCK])
+{
+ while (n_block--)
+ {
+ xor_block (iv, plain) ;
+ if (encrypt (iv, iv) != SUCCESS)
+ return FAILURE ;
+ copy_n_bytes (cipher, iv, N_BLOCK) ;
+ plain += N_BLOCK ;
+ cipher += N_BLOCK ;
+ }
+ return SUCCESS ;
+}
+
+/******************************************************************************/
+
+byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block)
+{
+ while (n_block--)
+ {
+ xor_block (iv, plain) ;
+ if (encrypt (iv, iv) != SUCCESS)
+ return FAILURE ;
+ copy_n_bytes (cipher, iv, N_BLOCK) ;
+ plain += N_BLOCK ;
+ cipher += N_BLOCK ;
+ }
+ return SUCCESS ;
+}
+
+/******************************************************************************/
+
+byte AES::decrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK])
+{
+ if (round)
+ {
+ byte s1 [N_BLOCK] ;
+ copy_and_key (s1, plain, (byte*) (key_sched + round * N_BLOCK)) ;
+ inv_shift_sub_rows (s1) ;
+
+ for (byte r = round ; --r ; )
+ {
+ byte s2 [N_BLOCK] ;
+ copy_and_key (s2, s1, (byte*) (key_sched + r * N_BLOCK)) ;
+ inv_mix_sub_columns (s1, s2) ;
+ }
+ copy_and_key (cipher, s1, (byte*) (key_sched)) ;
+ }
+ else
+ return FAILURE ;
+ return SUCCESS ;
+}
+
+/******************************************************************************/
+
+byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block, byte iv [N_BLOCK])
+{
+ while (n_block--)
+ {
+ byte tmp [N_BLOCK] ;
+ copy_n_bytes (tmp, cipher, N_BLOCK) ;
+ if (decrypt (cipher, plain) != SUCCESS)
+ return FAILURE ;
+ xor_block (plain, iv) ;
+ copy_n_bytes (iv, tmp, N_BLOCK) ;
+ plain += N_BLOCK ;
+ cipher += N_BLOCK;
+ }
+ return SUCCESS ;
+}
+
+/******************************************************************************/
+
+byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block)
+{
+ while (n_block--)
+ {
+ byte tmp [N_BLOCK] ;
+ copy_n_bytes (tmp, cipher, N_BLOCK) ;
+ if (decrypt (cipher, plain) != SUCCESS)
+ return FAILURE ;
+ xor_block (plain, iv) ;
+ copy_n_bytes (iv, tmp, N_BLOCK) ;
+ plain += N_BLOCK ;
+ cipher += N_BLOCK;
+ }
+ return SUCCESS ;
+}
+
+/*****************************************************************************/
+
+void AES::set_IV(unsigned long long int IVCl){
+ memcpy(iv,&IVCl,8);
+ memcpy(iv+8,&IVCl,8);
+ IVC = IVCl;
+}
+
+/******************************************************************************/
+
+void AES::iv_inc(){
+ IVC += 1;
+ memcpy(iv,&IVC,8);
+ memcpy(iv+8,&IVC,8);
+}
+
+/******************************************************************************/
+
+int AES::get_size(){
+ return size;
+}
+
+/******************************************************************************/
+
+void AES::set_size(int sizel){
+ size = sizel;
+}
+
+
+/******************************************************************************/
+
+void AES::get_IV(byte *out){
+ memcpy(out,&IVC,8);
+ memcpy(out+8,&IVC,8);
+}
+
+/******************************************************************************/
+
+void AES::calc_size_n_pad(int p_size){
+ int s_of_p = p_size - 1;
+ if ( s_of_p % N_BLOCK == 0){
+ size = s_of_p;
+ }else{
+ size = s_of_p + (N_BLOCK-(s_of_p % N_BLOCK));
+ }
+ pad = size - s_of_p;
+}
+
+/******************************************************************************/
+
+void AES::padPlaintext(void* in,byte* out)
+{
+ memcpy(out,in,size);
+ for (int i = size-pad; i < size; i++){;
+ out[i] = arr_pad[pad - 1];
+ }
+}
+
+/******************************************************************************/
+
+bool AES::CheckPad(byte* in,int lsize){
+ if (in[lsize-1] <= 0x0f){
+ int lpad = (int)in[lsize-1];
+ for (int i = lsize - 1; i >= lsize-lpad; i--){
+ if (arr_pad[lpad - 1] != in[i]){
+ return false;
+ }
+ }
+ }else{
+ return true;
+ }
+return true;
+}
+
+/******************************************************************************/
+
+void AES::printArray(byte output[],bool p_pad)
+{
+uint8_t i,j;
+uint8_t loops = size/N_BLOCK;
+uint8_t outp = N_BLOCK;
+for (j = 0; j < loops; j += 1){
+ if (p_pad && (j == (loops - 1)) ) { outp = N_BLOCK - pad; }
+ for (i = 0; i < outp; i++)
+ {
+ printf_P(PSTR("%d"),output[j*N_BLOCK + i]);
+ }
+}
+ printf_P(PSTR("\n"));
+}
+
+/******************************************************************************/
+
+void AES::printArray(byte output[],int sizel)
+{
+ for (int i = 0; i < sizel; i++)
+ {
+ printf_P(PSTR("%x"),output[i]);
+ }
+ printf_P(PSTR("\n"));
+}
+
+
+/******************************************************************************/
+
+void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits, byte ivl [N_BLOCK]){
+ calc_size_n_pad(size_p);
+ byte plain_p[get_size()];
+ padPlaintext(plain,plain_p);
+ int blocks = get_size() / N_BLOCK;
+ set_key (key, bits) ;
+ cbc_encrypt (plain_p, cipher, blocks, ivl);
+}
+
+/******************************************************************************/
+
+void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits){
+ calc_size_n_pad(size_p);
+ byte plain_p[get_size()];
+ padPlaintext(plain,plain_p);
+ int blocks = get_size() / N_BLOCK;
+ set_key (key, bits) ;
+ cbc_encrypt (plain_p, cipher, blocks);
+}
+
+/******************************************************************************/
+
+void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits, byte ivl [N_BLOCK]){
+ set_size(size_c);
+ int blocks = size_c / N_BLOCK;
+ set_key (key, bits);
+ cbc_decrypt (cipher,plain, blocks, ivl);
+}
+
+/******************************************************************************/
+
+void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits){
+ set_size(size_c);
+ int blocks = size_c / N_BLOCK;
+ set_key (key, bits);
+ cbc_decrypt (cipher,plain, blocks);
+}
+
+
+/******************************************************************************/
+
+#if defined(AES_LINUX)
+double AES::millis(){
+ gettimeofday(&tv, NULL);
+ return (tv.tv_sec + 0.000001 * tv.tv_usec);
+}
+#endif
--- /dev/null
+#include "AES.h"
+
+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+ 1. source code distributions include the above copyright notice, this
+ list of conditions and the following disclaimer;
+
+ 2. binary distributions include the above copyright notice, this list
+ of conditions and the following disclaimer in their documentation;
+
+ 3. the name of the copyright holder is not used to endorse products
+ built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue 09/09/2006
+
+ This is an AES implementation that uses only 8-bit byte operations on the
+ cipher state (there are options to use 32-bit types if available).
+
+ The combination of mix columns and byte substitution used here is based on
+ that developed by Karl Malbrain. His contribution is acknowledged.
+ */
+
+/* This version derived by Mark Tillotson 2012-01-23, tidied up, slimmed down
+ and tailored to 8-bit microcontroller abilities and Arduino datatypes.
+
+ The s-box and inverse s-box were retained as tables (0.5kB PROGMEM) but all
+ the other transformations are coded to save table space. Many efficiency
+ improvments to the routines mix_sub_columns() and inv_mix_sub_columns()
+ (mainly common sub-expression elimination).
+
+ Only the routines with precalculated subkey schedule are retained (together
+ with set_key() - this does however mean each AES object takes 240 bytes of
+ RAM, alas)
+
+ The CBC routines side-effect the iv argument (so that successive calls work
+ together correctly).
+
+ All the encryption and decryption routines work with plain == cipher for
+ in-place encryption, note.
+
+*/
+
+
+/* functions for finite field multiplication in the AES Galois field */
+
+/* code was modified by george spanos <spaniakos@gmail.com>
+ * 16/12/14
+ */
+
+// GF(2^8) stuff
+
+#define WPOLY 0x011B
+#define DPOLY 0x008D
+
+static const byte s_fwd [0x100] PROGMEM =
+{
+ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
+ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
+ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
+ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
+} ;
+
+static const byte s_inv [0x100] PROGMEM =
+{
+ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
+ 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
+ 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
+ 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
+ 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
+ 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
+ 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
+ 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
+ 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
+ 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
+ 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
+ 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
+ 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
+ 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
+ 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
+} ;
+
+// times 2 in the GF(2^8)
+#define f2(x) ((x) & 0x80 ? (x << 1) ^ WPOLY : x << 1)
+#define d2(x) (((x) >> 1) ^ ((x) & 1 ? DPOLY : 0))
+
+static byte s_box (byte x)
+{
+ // return fwd_affine (pgm_read_byte (&inv [x])) ;
+ return pgm_read_byte (& s_fwd [x]) ;
+}
+
+// Inverse Sbox
+static byte is_box (byte x)
+{
+ // return pgm_read_byte (&inv [inv_affine (x)]) ;
+ return pgm_read_byte (& s_inv [x]) ;
+}
+
+
+static void xor_block (byte * d, byte * s)
+{
+ for (byte i = 0 ; i < N_BLOCK ; i += 4)
+ {
+ *d++ ^= *s++ ; // some unrolling
+ *d++ ^= *s++ ;
+ *d++ ^= *s++ ;
+ *d++ ^= *s++ ;
+ }
+}
+
+static void copy_and_key (byte * d, byte * s, byte * k)
+{
+ for (byte i = 0 ; i < N_BLOCK ; i += 4)
+ {
+ *d++ = *s++ ^ *k++ ; // some unrolling
+ *d++ = *s++ ^ *k++ ;
+ *d++ = *s++ ^ *k++ ;
+ *d++ = *s++ ^ *k++ ;
+ }
+}
+
+// #define add_round_key(d, k) xor_block (d, k)
+
+/* SUB ROW PHASE */
+
+static void shift_sub_rows (byte st [N_BLOCK])
+{
+ st [0] = s_box (st [0]) ; st [4] = s_box (st [4]) ;
+ st [8] = s_box (st [8]) ; st [12] = s_box (st [12]) ;
+
+ byte tt = st [1] ;
+ st [1] = s_box (st [5]) ; st [5] = s_box (st [9]) ;
+ st [9] = s_box (st [13]) ; st [13] = s_box (tt) ;
+
+ tt = st[2] ; st [2] = s_box (st [10]) ; st [10] = s_box (tt) ;
+ tt = st[6] ; st [6] = s_box (st [14]) ; st [14] = s_box (tt) ;
+
+ tt = st[15] ;
+ st [15] = s_box (st [11]) ; st [11] = s_box (st [7]) ;
+ st [7] = s_box (st [3]) ; st [3] = s_box (tt) ;
+}
+
+static void inv_shift_sub_rows (byte st[N_BLOCK])
+{
+ st [0] = is_box (st[0]) ; st [4] = is_box (st [4]);
+ st [8] = is_box (st[8]) ; st [12] = is_box (st [12]);
+
+ byte tt = st[13] ;
+ st [13] = is_box (st [9]) ; st [9] = is_box (st [5]) ;
+ st [5] = is_box (st [1]) ; st [1] = is_box (tt) ;
+
+ tt = st [2] ; st [2] = is_box (st [10]) ; st [10] = is_box (tt) ;
+ tt = st [6] ; st [6] = is_box (st [14]) ; st [14] = is_box (tt) ;
+
+ tt = st [3] ;
+ st [3] = is_box (st [7]) ; st [7] = is_box (st [11]) ;
+ st [11] = is_box (st [15]) ; st [15] = is_box (tt) ;
+}
+
+/* SUB COLUMNS PHASE */
+
+static void mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK])
+{
+ byte j = 5 ;
+ byte k = 10 ;
+ byte l = 15 ;
+ for (byte i = 0 ; i < N_BLOCK ; i += N_COL)
+ {
+ byte a = st [i] ;
+ byte b = st [j] ; j = (j+N_COL) & 15 ;
+ byte c = st [k] ; k = (k+N_COL) & 15 ;
+ byte d = st [l] ; l = (l+N_COL) & 15 ;
+ byte a1 = s_box (a), b1 = s_box (b), c1 = s_box (c), d1 = s_box (d) ;
+ byte a2 = f2(a1), b2 = f2(b1), c2 = f2(c1), d2 = f2(d1) ;
+ dt[i] = a2 ^ b2^b1 ^ c1 ^ d1 ;
+ dt[i+1] = a1 ^ b2 ^ c2^c1 ^ d1 ;
+ dt[i+2] = a1 ^ b1 ^ c2 ^ d2^d1 ;
+ dt[i+3] = a2^a1 ^ b1 ^ c1 ^ d2 ;
+ }
+}
+
+static void inv_mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK])
+{
+ for (byte i = 0 ; i < N_BLOCK ; i += N_COL)
+ {
+ byte a1 = st [i] ;
+ byte b1 = st [i+1] ;
+ byte c1 = st [i+2] ;
+ byte d1 = st [i+3] ;
+ byte a2 = f2(a1), b2 = f2(b1), c2 = f2(c1), d2 = f2(d1) ;
+ byte a4 = f2(a2), b4 = f2(b2), c4 = f2(c2), d4 = f2(d2) ;
+ byte a8 = f2(a4), b8 = f2(b4), c8 = f2(c4), d8 = f2(d4) ;
+ byte a9 = a8 ^ a1,b9 = b8 ^ b1,c9 = c8 ^ c1,d9 = d8 ^ d1 ;
+ byte ac = a8 ^ a4,bc = b8 ^ b4,cc = c8 ^ c4,dc = d8 ^ d4 ;
+
+ dt[i] = is_box (ac^a2 ^ b9^b2 ^ cc^c1 ^ d9) ;
+ dt[(i+5)&15] = is_box (a9 ^ bc^b2 ^ c9^c2 ^ dc^d1) ;
+ dt[(i+10)&15] = is_box (ac^a1 ^ b9 ^ cc^c2 ^ d9^d2) ;
+ dt[(i+15)&15] = is_box (a9^a2 ^ bc^b1 ^ c9 ^ dc^d2) ;
+ }
+}
+
+/******************************************************************************/
+
+AES::AES(){
+ byte ar_iv[8] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 };
+ memcpy(iv,ar_iv,8);
+ memcpy(iv+8,ar_iv,8);
+ arr_pad[0] = 0x01;
+ arr_pad[1] = 0x02;
+ arr_pad[2] = 0x03;
+ arr_pad[3] = 0x04;
+ arr_pad[4] = 0x05;
+ arr_pad[5] = 0x06;
+ arr_pad[6] = 0x07;
+ arr_pad[7] = 0x08;
+ arr_pad[8] = 0x09;
+ arr_pad[9] = 0x0a;
+ arr_pad[10] = 0x0b;
+ arr_pad[11] = 0x0c;
+ arr_pad[12] = 0x0d;
+ arr_pad[13] = 0x0e;
+ arr_pad[14] = 0x0f;
+}
+
+/******************************************************************************/
+
+byte AES::set_key (byte key [], int keylen)
+{
+ byte hi ;
+ switch (keylen)
+ {
+ case 16:
+ case 128:
+ keylen = 16; // 10 rounds
+ round = 10 ;
+ break;
+ case 24:
+ case 192:
+ keylen = 24; // 12 rounds
+ round = 12 ;
+ break;
+ case 32:
+ case 256:
+ keylen = 32; // 14 rounds
+ round = 14 ;
+ break;
+ default:
+ round = 0;
+ return FAILURE;
+ }
+ hi = (round + 1) << 4 ;
+ copy_n_bytes (key_sched, key, keylen) ;
+ byte t[4] ;
+ byte next = keylen ;
+ for (byte cc = keylen, rc = 1 ; cc < hi ; cc += N_COL)
+ {
+ for (byte i = 0 ; i < N_COL ; i++)
+ t[i] = key_sched [cc-4+i] ;
+ if (cc == next)
+ {
+ next += keylen ;
+ byte ttt = t[0] ;
+ t[0] = s_box (t[1]) ^ rc ;
+ t[1] = s_box (t[2]) ;
+ t[2] = s_box (t[3]) ;
+ t[3] = s_box (ttt) ;
+ rc = f2 (rc) ;
+ }
+ else if (keylen == 32 && (cc & 31) == 16)
+ {
+ for (byte i = 0 ; i < 4 ; i++)
+ t[i] = s_box (t[i]) ;
+ }
+ byte tt = cc - keylen ;
+ for (byte i = 0 ; i < N_COL ; i++)
+ key_sched [cc + i] = key_sched [tt + i] ^ t[i] ;
+ }
+ return SUCCESS ;
+}
+
+/******************************************************************************/
+
+void AES::clean ()
+{
+ for (byte i = 0 ; i < KEY_SCHEDULE_BYTES ; i++)
+ key_sched [i] = 0 ;
+ round = 0 ;
+}
+
+/******************************************************************************/
+
+void AES::copy_n_bytes (byte * d, byte * s, byte nn)
+{
+ while (nn >= 4)
+ {
+ *d++ = *s++ ; // some unrolling
+ *d++ = *s++ ;
+ *d++ = *s++ ;
+ *d++ = *s++ ;
+ nn -= 4 ;
+ }
+ while (nn--)
+ *d++ = *s++ ;
+}
+
+/******************************************************************************/
+
+byte AES::encrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK])
+{
+ if (round)
+ {
+ byte s1 [N_BLOCK], r ;
+ copy_and_key (s1, plain, (byte*) (key_sched)) ;
+
+ for (r = 1 ; r < round ; r++)
+ {
+ byte s2 [N_BLOCK] ;
+ mix_sub_columns (s2, s1) ;
+ copy_and_key (s1, s2, (byte*) (key_sched + r * N_BLOCK)) ;
+ }
+ shift_sub_rows (s1) ;
+ copy_and_key (cipher, s1, (byte*) (key_sched + r * N_BLOCK)) ;
+ }
+ else
+ return FAILURE ;
+ return SUCCESS ;
+}
+
+/******************************************************************************/
+
+byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block, byte iv [N_BLOCK])
+{
+ while (n_block--)
+ {
+ xor_block (iv, plain) ;
+ if (encrypt (iv, iv) != SUCCESS)
+ return FAILURE ;
+ copy_n_bytes (cipher, iv, N_BLOCK) ;
+ plain += N_BLOCK ;
+ cipher += N_BLOCK ;
+ }
+ return SUCCESS ;
+}
+
+/******************************************************************************/
+
+byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block)
+{
+ while (n_block--)
+ {
+ xor_block (iv, plain) ;
+ if (encrypt (iv, iv) != SUCCESS)
+ return FAILURE ;
+ copy_n_bytes (cipher, iv, N_BLOCK) ;
+ plain += N_BLOCK ;
+ cipher += N_BLOCK ;
+ }
+ return SUCCESS ;
+}
+
+/******************************************************************************/
+
+byte AES::decrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK])
+{
+ if (round)
+ {
+ byte s1 [N_BLOCK] ;
+ copy_and_key (s1, plain, (byte*) (key_sched + round * N_BLOCK)) ;
+ inv_shift_sub_rows (s1) ;
+
+ for (byte r = round ; --r ; )
+ {
+ byte s2 [N_BLOCK] ;
+ copy_and_key (s2, s1, (byte*) (key_sched + r * N_BLOCK)) ;
+ inv_mix_sub_columns (s1, s2) ;
+ }
+ copy_and_key (cipher, s1, (byte*) (key_sched)) ;
+ }
+ else
+ return FAILURE ;
+ return SUCCESS ;
+}
+
+/******************************************************************************/
+
+byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block, byte iv [N_BLOCK])
+{
+ while (n_block--)
+ {
+ byte tmp [N_BLOCK] ;
+ copy_n_bytes (tmp, cipher, N_BLOCK) ;
+ if (decrypt (cipher, plain) != SUCCESS)
+ return FAILURE ;
+ xor_block (plain, iv) ;
+ copy_n_bytes (iv, tmp, N_BLOCK) ;
+ plain += N_BLOCK ;
+ cipher += N_BLOCK;
+ }
+ return SUCCESS ;
+}
+
+/******************************************************************************/
+
+byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block)
+{
+ while (n_block--)
+ {
+ byte tmp [N_BLOCK] ;
+ copy_n_bytes (tmp, cipher, N_BLOCK) ;
+ if (decrypt (cipher, plain) != SUCCESS)
+ return FAILURE ;
+ xor_block (plain, iv) ;
+ copy_n_bytes (iv, tmp, N_BLOCK) ;
+ plain += N_BLOCK ;
+ cipher += N_BLOCK;
+ }
+ return SUCCESS ;
+}
+
+/*****************************************************************************/
+
+void AES::set_IV(unsigned long long int IVCl){
+ memcpy(iv,&IVCl,8);
+ memcpy(iv+8,&IVCl,8);
+ IVC = IVCl;
+}
+
+/******************************************************************************/
+
+void AES::iv_inc(){
+ IVC += 1;
+ memcpy(iv,&IVC,8);
+ memcpy(iv+8,&IVC,8);
+}
+
+/******************************************************************************/
+
+int AES::get_size(){
+ return size;
+}
+
+/******************************************************************************/
+
+void AES::set_size(int sizel){
+ size = sizel;
+}
+
+
+/******************************************************************************/
+
+void AES::get_IV(byte *out){
+ memcpy(out,&IVC,8);
+ memcpy(out+8,&IVC,8);
+}
+
+/******************************************************************************/
+
+void AES::calc_size_n_pad(int p_size){
+ int s_of_p = p_size - 1;
+ if ( s_of_p % N_BLOCK == 0){
+ size = s_of_p;
+ }else{
+ size = s_of_p + (N_BLOCK-(s_of_p % N_BLOCK));
+ }
+ pad = size - s_of_p;
+}
+
+/******************************************************************************/
+
+void AES::padPlaintext(void* in,byte* out)
+{
+ memcpy(out,in,size);
+ for (int i = size-pad; i < size; i++){;
+ out[i] = arr_pad[pad - 1];
+ }
+}
+
+/******************************************************************************/
+
+bool AES::CheckPad(byte* in,int lsize){
+ if (in[lsize-1] <= 0x0f){
+ int lpad = (int)in[lsize-1];
+ for (int i = lsize - 1; i >= lsize-lpad; i--){
+ if (arr_pad[lpad - 1] != in[i]){
+ return false;
+ }
+ }
+ }else{
+ return true;
+ }
+return true;
+}
+
+/******************************************************************************/
+
+void AES::printArray(byte output[],bool p_pad)
+{
+uint8_t i,j;
+uint8_t loops = size/N_BLOCK;
+uint8_t outp = N_BLOCK;
+for (j = 0; j < loops; j += 1){
+ if (p_pad && (j == (loops - 1)) ) { outp = N_BLOCK - pad; }
+ for (i = 0; i < outp; i++)
+ {
+ printf_P(PSTR("%c"),output[j*N_BLOCK + i]);
+ }
+}
+ printf_P(PSTR("\n"));
+}
+
+/******************************************************************************/
+
+void AES::printArray(byte output[],int sizel)
+{
+ for (int i = 0; i < sizel; i++)
+ {
+ printf_P(PSTR("%x"),output[i]);
+ }
+ printf_P(PSTR("\n"));
+}
+
+
+/******************************************************************************/
+
+void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits, byte ivl [N_BLOCK]){
+ calc_size_n_pad(size_p);
+ byte plain_p[get_size()];
+ padPlaintext(plain,plain_p);
+ int blocks = get_size() / N_BLOCK;
+ set_key (key, bits) ;
+ cbc_encrypt (plain_p, cipher, blocks, ivl);
+}
+
+/******************************************************************************/
+
+void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits){
+ calc_size_n_pad(size_p);
+ byte plain_p[get_size()];
+ padPlaintext(plain,plain_p);
+ int blocks = get_size() / N_BLOCK;
+ set_key (key, bits) ;
+ cbc_encrypt (plain_p, cipher, blocks);
+}
+
+/******************************************************************************/
+
+void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits, byte ivl [N_BLOCK]){
+ set_size(size_c);
+ int blocks = size_c / N_BLOCK;
+ set_key (key, bits);
+ cbc_decrypt (cipher,plain, blocks, ivl);
+}
+
+/******************************************************************************/
+
+void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits){
+ set_size(size_c);
+ int blocks = size_c / N_BLOCK;
+ set_key (key, bits);
+ cbc_decrypt (cipher,plain, blocks);
+}
+
+
+/******************************************************************************/
+
+#if defined(AES_LINUX)
+double AES::millis(){
+ gettimeofday(&tv, NULL);
+ return (tv.tv_sec + 0.000001 * tv.tv_usec);
+}
+#endif
--- /dev/null
+#ifndef __AES_H__
+#define __AES_H__
+
+#include "AES_config.h"
+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+ 1. source code distributions include the above copyright notice, this
+ list of conditions and the following disclaimer;
+
+ 2. binary distributions include the above copyright notice, this list
+ of conditions and the following disclaimer in their documentation;
+
+ 3. the name of the copyright holder is not used to endorse products
+ built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue 09/09/2006
+
+ This is an AES implementation that uses only 8-bit byte operations on the
+ cipher state.
+ */
+
+ /* code was modified by george spanos <spaniakos@gmail.com>
+ * 16/12/14
+ */
+
+class AES
+{
+ public:
+
+/* The following calls are for a precomputed key schedule
+
+ NOTE: If the length_type used for the key length is an
+ unsigned 8-bit character, a key length of 256 bits must
+ be entered as a length in bytes (valid inputs are hence
+ 128, 192, 16, 24 and 32).
+*/
+ /** \fn AES()
+ * \brief AES constructor
+ *
+ * This function initialized an instance of AES.
+ */
+ AES();
+
+ /** Set the cipher key for the pre-keyed version.
+ * @param key[] pointer to the key string.
+ * @param keylen Integer that indicates the length of the key.
+ * @note NOTE: If the length_type used for the key length is an unsigned 8-bit character,
+ * a key length of 256 bits must be entered as a length in bytes
+ * (valid inputs are hence 128, 192, 16, 24 and 32).
+ *
+ */
+ byte set_key (byte key[], int keylen) ;
+
+ /** clean up subkeys after use.
+ *
+ */
+ void clean () ; // delete key schedule after use
+
+ /** copying and xoring utilities.
+ * @param *AESt byte pointer of the AEStination array.
+ * @param *src byte pointer of the source array.
+ * @param n byte, indicating the sizeof the bytes to be copied.
+ * @note this is an alternative for memcpy(void *s1,const void *s2, site_t n),
+ * i have not updated the function in the implementation yet, but it is considered a future plan.
+ *
+ */
+ void copy_n_bytes (byte * AESt, byte * src, byte n) ;
+
+ /** Encrypt a single block of 16 bytes .
+ * @param plain[N_BLOCK] Array of the plaintext.
+ * @param cipher[N_BLOCK] Array of the ciphertext.
+ * @note The N_BLOCK is defined in AES_config.h as,
+ * @code #define N_ROW 4
+ * #define N_COL 4
+ * #define N_BLOCK (N_ROW * N_COL)
+ * @endcode
+ * Changed to that will change the Block_size.
+ * @Return 0 if SUCCESS or -1 if FAILURE
+ *
+ */
+ byte encrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK]) ;
+
+ /** CBC encrypt a number of blocks (input and return an IV).
+ *
+ * @param *plain Pointer, points to the plaintex.
+ * @param *cipher Pointer, points to the ciphertext that will be created.
+ * @param n_block integer, indicated the number of blocks to be ciphered.
+ * @param iv[N_BLOCK] byte Array that holds the IV (initialization vector).
+ * @Return 0 if SUCCESS or -1 if FAILURE
+ *
+ */
+ byte cbc_encrypt (byte * plain, byte * cipher, int n_block, byte iv [N_BLOCK]) ;
+
+ /** CBC encrypt a number of blocks (input and return an IV).
+ *
+ * @param *plain Pointer, points to the plaintex.
+ * @param *cipher Pointer, points to the ciphertext that will be created.
+ * @param n_block integer, indicated the number of blocks to be ciphered.
+ * @Return 0 if SUCCESS or -1 if FAILURE
+ *
+ */
+ byte cbc_encrypt (byte * plain, byte * cipher, int n_block) ;
+
+
+ /** Decrypt a single block of 16 bytes
+ * @param cipher[N_BLOCK] Array of the ciphertext.
+ * @param plain[N_BLOCK] Array of the plaintext.
+ * @note The N_BLOCK is defined in AES_config.h as,
+ * @code #define N_ROW 4
+ * #define N_COL 4
+ * #define N_BLOCK (N_ROW * N_COL)
+ * @endcode
+ * Changed to that will change the Block_size.
+ * @Return 0 if SUCCESS or -1 if FAILURE
+ *
+ */
+ byte decrypt (byte cipher [N_BLOCK], byte plain [N_BLOCK]) ;
+
+ /** CBC decrypt a number of blocks (input and return an IV)
+ *
+ * @param *cipher Pointer, points to the ciphertext that will be created.
+ * @param *plain Pointer, points to the plaintex.
+ * @param n_block integer, indicated the number of blocks to be ciphered.
+ * @param iv[N_BLOCK] byte Array that holds the IV (initialization vector).
+ * @Return 0 if SUCCESS or -1 if FAILURE
+ *
+ */
+ byte cbc_decrypt (byte * cipher, byte * plain, int n_block, byte iv [N_BLOCK]) ;
+
+ /** CBC decrypt a number of blocks (input and return an IV)
+ *
+ * @param *cipher Pointer, points to the ciphertext that will be created.
+ * @param *plain Pointer, points to the plaintex.
+ * @param n_block integer, indicated the number of blocks to be ciphered.
+ * @Return 0 if SUCCESS or -1 if FAILURE
+ *
+ */
+ byte cbc_decrypt (byte * cipher, byte * plain, int n_block) ;
+
+ /** Sets IV (initialization vector) and IVC (IV counter).
+ * This function changes the ivc and iv variables needed for AES.
+ *
+ * @param IVCl int or hex value of iv , ex. 0x0000000000000001
+ * @note example:
+ * @code unsigned long long int my_iv = 01234567; @endcode
+ */
+ void set_IV(unsigned long long int IVCl);
+
+ /** increase the iv (initialization vector) and IVC (IV counter) by 1
+ *
+ * This function increased the VI by one step in order to have a different IV each time
+ *
+ */
+ void iv_inc();
+
+ /** Getter method for size
+ *
+ * This function return the size
+ * @return an integer, that is the size of the of the padded plaintext,
+ * thus, the size of the ciphertext.
+ */
+ int get_size();
+
+ /** Setter method for size
+ *
+ * This function sets the size of the plaintext+pad
+ *
+ */
+ void set_size(int sizel);
+
+ /** Getter method for IV
+ *
+ * This function return the IV
+ * @param out byte pointer that gets the IV.
+ * @return none, the IV is writed to the out pointer.
+ */
+ void get_IV(byte *out);
+
+ /** Calculates the size of the plaintext and the padding.
+ *
+ * Calculates the size of theplaintext with the padding
+ * and the size of the padding needed. Moreover it stores them in their class variables.
+ *
+ * @param p_size the size of the byte array ex sizeof(plaintext)
+ */
+ void calc_size_n_pad(int p_size);
+
+ /** Pads the plaintext
+ *
+ * This function pads the plaintext and returns an char array with the
+ * plaintext and the padding in order for the plaintext to be compatible with
+ * 16bit size blocks required by AES
+ *
+ * @param in the string of the plaintext in a byte array
+ * @param out The string of the out array.
+ * @return no return, The padded plaintext is stored in the out pointer.
+ */
+ void padPlaintext(void* in,byte* out);
+
+ /** Check the if the padding is correct.
+ *
+ * This functions checks the padding of the plaintext.
+ *
+ * @param in the string of the plaintext in a byte array
+ * @param size the size of the string
+ * @return true if correct / false if not
+ */
+ bool CheckPad(byte* in,int size);
+
+ /** Prints the array given.
+ *
+ * This function prints the given array and pad,
+ * It is mainlly used for debugging purpuses or to output the string.
+ *
+ * @param output[] the string of the text in a byte array
+ * @param p_pad optional, used to print with out the padding characters
+ */
+ void printArray(byte output[],bool p_pad = true);
+
+ /** Prints the array given.
+ *
+ * This function prints the given array in Hexadecimal.
+ *
+ * @param output[] the string of the text in a byte array
+ * @param sizel the size of the array.
+ */
+ void printArray(byte output[],int sizel);
+
+ /** User friendly implementation of AES-CBC encryption.
+ *
+ * @param *plain pointer to the plaintext
+ * @param size_p size of the plaintext
+ * @param *cipher pointer to the ciphertext
+ * @param *key pointer to the key that will be used.
+ * @param bits bits of the encryption/decrpytion
+ * @param ivl[N_BLOCK] the initialization vector IV that will be used for encryption.
+ * @note The key will be stored in class variable.
+ */
+ void do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits, byte ivl [N_BLOCK]);
+
+ /** User friendly implementation of AES-CBC encryption.
+ *
+ * @param *plain pointer to the plaintext
+ * @param size_p size of the plaintext
+ * @param *cipher pointer to the ciphertext
+ * @param *key pointer to the key that will be used.
+ * @param bits bits of the encryption/decrpytion
+ * @note The key will be stored in class variable.
+ */
+ void do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits);
+
+ /** User friendly implementation of AES-CBC decryption.
+ *
+ * @param *cipher pointer to the ciphertext
+ * @param size_c size of the ciphertext
+ * @param *plain pointer to the plaintext
+ * @param *key pointer to the key that will be used.
+ * @param bits bits of the encryption/decrpytion
+ * @param ivl[N_BLOCK] the initialization vector IV that will be used for decryption.
+ * @note The key will be stored in class variable.
+ */
+ void do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits, byte ivl [N_BLOCK]);
+
+ /** User friendly implementation of AES-CBC decryption.
+ *
+ * @param *cipher pointer to the ciphertext
+ * @param size_c size of the ciphertext
+ * @param *plain pointer to the plaintext
+ * @param *key pointer to the key that will be used.
+ * @param bits bits of the encryption/decrpytion
+ * @note The key will be stored in class variable.
+ */
+ void do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits);
+
+ #if defined(AES_LINUX)
+ /**
+ * used in linux in order to retrieve the time in milliseconds.
+ *
+ * @return returns the milliseconds in a double format.
+ */
+ double millis();
+ #endif
+ private:
+ int round ;/**< holds the number of rounds to be used. */
+ byte key_sched [KEY_SCHEDULE_BYTES] ;/**< holds the pre-computed key for the encryption/decrpytion. */
+ unsigned long long int IVC;/**< holds the initialization vector counter in numerical format. */
+ byte iv[16];/**< holds the initialization vector that will be used in the cipher. */
+ int pad;/**< holds the size of the padding. */
+ int size;/**< hold the size of the plaintext to be ciphered */
+ #if defined(AES_LINUX)
+ timeval tv;/**< holds the time value on linux */
+ byte arr_pad[15];/**< holds the hexadecimal padding values on linux */
+ #else
+ byte arr_pad[15] = { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };/**< holds the hexadecimal padding values */
+ #endif
+} ;
+
+
+#endif
+
+/**
+ * @example aes.ino
+ * <b>For Arduino</b><br>
+ * <b>Updated: spaniakos 2015 </b><br>
+ *
+ * This is an example of how to use AES in CBC mode easily.
+ * The text and keys can be either in HEX or String format.<br />
+ */
+
+ /**
+ * @example aes.cpp
+ * <b>For Rasberry pi</b><br>
+ * <b>Updated: spaniakos 2015 </b><br>
+ *
+ * This is an example of how to use AES in CBC mode easily.
+ * The text and keys can be either in HEX or String format.<br />
+ */
+
+ /**
+ * @example test_vectors.ino
+ * <b>For Arduino</b><br>
+ * <b>Updated: spaniakos 2015 </b><br>
+ *
+ * This is an example of monte carlo test vectors, in order to justify the effectiveness of the algorithm.<br />
+ * plus is a classical approach to the AES encryption library with out the easy to use add-on modifications.
+ */
+
+ /**
+ * @example test_vectors.cpp
+ * <b>For Rasberry pi</b><br>
+ * <b>Updated: spaniakos 2015 </b><br>
+ *
+ * This is an example of monte carlo test vectors, in order to justify the effectiveness of the algorithm.<br />
+ * plus is a classical approach to the AES encryption library with out the easy to use add-on modifications.
+ */
+
+/**
+ * @mainpage AES library for Arduino and Raspberry pi.
+ *
+ * @section Goals design Goals
+ *
+ * This library is AESigned to be...
+ * @li Fast and efficient.
+ * @li Able to effectively encrypt and decrypt any size of string.
+ * @li Able to encrypt and decrypt using AES
+ * @li Able to encrypt and decrypt using AES-CBC
+ * @li Easy for the user to use in his programs.
+ *
+ * @section Acknowledgements Acknowledgements
+ * This is an AES library for the Arduino, based on tzikis's AES library, which you can find <a href= "https://github.com/tzikis/arduino">here:</a>.<br />
+ * Tzikis library was based on scottmac`s library, which you can find <a href="https://github.com/scottmac/arduino">here:</a><br />
+ *
+ * @section Installation Installation
+ * <h3>Arduino</h3>
+ * Create a folder named _AES_ in the _libraries_ folder inside your Arduino sketch folder. If the
+ * libraries folder doesn't exist, create it. Then copy everything inside. (re)launch the Arduino IDE.<br />
+ * You're done. Time for a mojito
+ *
+ * <h3>Raspberry pi</h3>
+ * <b>install</b><br /><br />
+ *
+ * sudo make install<br />
+ * cd examples_Rpi<br />
+ * make<br /><br />
+ *
+ * <b>What to do after changes to the library</b><br /><br />
+ * sudo make clean<br />
+ * sudo make install<br />
+ * cd examples_Rpi<br />
+ * make clean<br />
+ * make<br /><br />
+ * <b>What to do after changes to a sketch</b><br /><br />
+ * cd examples_Rpi<br />
+ * make <sketch><br /><br />
+ * or <br />
+ * make clean<br />
+ * make<br /><br /><br />
+ * <b>How to start a sketch</b><br /><br />
+ * cd examples_Rpi<br />
+ * sudo ./<sketch><br /><br />
+ *
+ * @section News News
+ *
+ * If issues are discovered with the documentation, please report them <a href="https://github.com/spaniakos/spaniakos.github.io/issues"> here</a>
+ * @section Useful Useful References
+ *
+ * Please refer to:
+ *
+ * @li <a href="http://spaniakos.github.io/AES/classAES.html"><b>AES</b> Class Documentation</a>
+ * @li <a href="https://github.com/spaniakos/AES/archive/master.zip"><b>Download</b></a>
+ * @li <a href="https://github.com/spaniakos/AES/"><b>Source Code</b></a>
+ * @li <a href="http://spaniakos.github.io/">All spaniakos Documentation Main Page</a>
+ *
+ * @section Board_Support Board Support
+ *
+ * Most standard Arduino based boards are supported:
+ * - Arduino
+ * - Intel Galileo support
+ * - Raspberry Pi Support
+ *
+ * - The library has not been tested to other boards, but it should suppport ATMega 328 based boards,Mega Boards,Arduino Due,ATTiny board
+ */
--- /dev/null
+/* code was modified by george spanos <spaniakos@gmail.com>
+ * 16/12/14
+ */
+
+#ifndef __AES_CONFIG_H__
+#define __AES_CONFIG_H__
+
+#if (defined(__linux) || defined(linux)) && !defined(__ARDUINO_X86__)
+
+ #define AES_LINUX
+
+ #include <stdint.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <sys/time.h>
+ #include <unistd.h>
+#else
+ #include <Arduino.h>
+#endif
+
+#include <stdint.h>
+#include <string.h>
+
+#if defined(__ARDUINO_X86__) || (defined (__linux) || defined (linux))
+ #undef PROGMEM
+ #define PROGMEM __attribute__(( section(".progmem.data") ))
+ #define pgm_read_byte(p) (*(p))
+ typedef unsigned char byte;
+ #define printf_P printf
+ #define PSTR(x) (x)
+#else
+#if (defined(__AVR__))
+#include <avr/pgmspace.h>
+ #else
+#include <pgmspace.h>
+#endif
+#endif
+
+#define N_ROW 4
+#define N_COL 4
+#define N_BLOCK (N_ROW * N_COL)
+#define N_MAX_ROUNDS 14
+#define KEY_SCHEDULE_BYTES ((N_MAX_ROUNDS + 1) * N_BLOCK)
+#define SUCCESS (0)
+#define FAILURE (-1)
+
+#endif
--- /dev/null
+/* code was modified by george spanos <spaniakos@gmail.com>
+ * 16/12/14
+ */
+
+#ifndef __AES_CONFIG_H__
+#define __AES_CONFIG_H__
+
+#if (defined(__linux) || defined(linux)) && !defined(__ARDUINO_X86__)
+
+ #define AES_LINUX
+
+ #include <stdint.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <sys/time.h>
+ #include <unistd.h>
+#else
+ #include <Arduino.h>
+#endif
+
+#include <stdint.h>
+#include <string.h>
+
+#if defined(__ARDUINO_X86__) || (defined (__linux) || defined (linux))
+ #undef PROGMEM
+ #define PROGMEM __attribute__(( section(".progmem.data") ))
+ #define pgm_read_byte(p) (*(p))
+ typedef unsigned char byte;
+ #define printf_P printf
+ #define PSTR(x) (x)
+#else
+ #include <avr/pgmspace.h>
+#endif
+
+#define N_ROW 4
+#define N_COL 4
+#define N_BLOCK (N_ROW * N_COL)
+#define N_MAX_ROUNDS 14
+#define KEY_SCHEDULE_BYTES ((N_MAX_ROUNDS + 1) * N_BLOCK)
+#define SUCCESS (0)
+#define FAILURE (-1)
+
+#endif
--- /dev/null
+# Doxyfile 1.8.6
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = "AES Encryption Library for Arduino and Raspberry Pi"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF = "Spaniakos - AES Encryption Library for Arduino and Raspberry Pi"
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = "../Documentations/AES"
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C.
+#
+# Note For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING = ino=c \
+ pde=c
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = YES
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = NO
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = YES
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = NO
+
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = NO
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. Do not use file names with spaces, bibtex cannot handle them. See
+# also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = ./
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.cxx \
+ *.cpp \
+ *.c++ \
+ *.java \
+ *.ii \
+ *.ixx \
+ *.ipp \
+ *.i++ \
+ *.inl \
+ *.idl \
+ *.ddl \
+ *.odl \
+ *.h \
+ *.hh \
+ *.hxx \
+ *.hpp \
+ *.h++ \
+ *.cs \
+ *.d \
+ *.php \
+ *.php4 \
+ *.php5 \
+ *.phtml \
+ *.inc \
+ *.m \
+ *.markdown \
+ *.md \
+ *.mm \
+ *.dox \
+ *.py \
+ *.f90 \
+ *.f \
+ *.for \
+ *.tcl \
+ *.vhd \
+ *.vhdl \
+ *.ucf \
+ *.qsf \
+ *.as \
+ *.js
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH = examples \
+ examples_RPi \
+ examples_Rpi
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = YES
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = YES
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the
+# clang parser (see: http://clang.llvm.org/) for more acurate parsing at the
+# cost of reduced performance. This can be particularly helpful with template
+# rich C++ code for which doxygen's built-in parser lacks the necessary type
+# information.
+# Note: The availability of this option depends on whether or not doxygen was
+# compiled with the --with-libclang option.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 10
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
+# defined cascading style sheet that is included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefor more robust against future updates.
+# Doxygen will copy the style sheet file to the output directory. For an example
+# see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET = doxygen-custom.css
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = YES
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavours of web server based searching depending on the
+# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
+# searching and an index file used by the script. When EXTERNAL_SEARCH is
+# enabled the indexing and searching needs to be provided by external tools. See
+# the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
+# replace them by respectively the title of the page, the current date and time,
+# only the current date, the version number of doxygen, the project name (see
+# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = NO
+
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all refrences to function-like macros that are alone on a line, have an
+# all uppercase name, and do not end with a semicolon. Such function macros are
+# typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have an unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font n the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
--- /dev/null
+#############################################################################
+#
+# Makefile for AES on Raspberry Pi
+#
+# License: GPL (General Public License)
+# Author: Georgios Spanos (spaniakos) <spaniakos@gmail.com>
+# Date: 02/12/2014
+#
+# Description:
+# ------------
+# use make all and mak install to install the library
+# You can change the install directory by editing the LIBDIR line
+#
+PREFIX=/usr/local
+
+# Library parameters
+# where to put the lib
+LIBDIR=$(PREFIX)/lib
+# lib name
+LIB=libAES
+# shared library name
+LIBNAME=$(LIB).so.1.0
+
+# Where to put the header files
+HEADER_DIR=${PREFIX}/include/AES
+
+# The recommended compiler flags for the Raspberry Pi
+CCFLAGS=-Ofast -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s
+
+# make all
+# reinstall the library after each recompilation
+all: libAES
+
+# Make the library
+libAES: AES.o
+ g++ -shared -Wl,-soname,$@.so.1 ${CCFLAGS} -o ${LIBNAME} $^
+
+# Library parts
+AES.o: AES.cpp
+ g++ -Wall -fPIC ${CCFLAGS} -c $^
+
+# clear build files
+clean:
+ rm -rf *.o ${LIB}.*
+ rm -rf ${LIBDIR}/${LIB}.*
+ rm -rf ${HEADER_DIR}
+
+install: all install-libs install-headers
+
+# Install the library to LIBPATH
+install-libs:
+ @echo "[Installing Libs]"
+ @if ( test ! -d $(PREFIX)/lib ) ; then mkdir -p $(PREFIX)/lib ; fi
+ @install -m 0755 ${LIBNAME} ${LIBDIR}
+ @ln -sf ${LIBDIR}/${LIBNAME} ${LIBDIR}/${LIB}.so.1
+ @ln -sf ${LIBDIR}/${LIBNAME} ${LIBDIR}/${LIB}.so
+ @ldconfig
+
+install-headers:
+ @echo "[Installing Headers]"
+ @if ( test ! -d ${HEADER_DIR} ) ; then mkdir -p ${HEADER_DIR} ; fi
+ @install -m 0644 *.h ${HEADER_DIR}
--- /dev/null
+### Arduino
+Just run the sketch after loading the libraries.
+
+### Raspberry pi
+install
+```
+sudo make install
+cd examples_Rpi
+make
+```
+
+What to do after changes to the library
+```
+sudo make clean
+sudo make install
+cd examples_Rpi
+make clean
+make
+```
+
+What to do after changes to a sketch
+```
+cd examples_Rpi
+make <sketch>
+
+or
+make clean
+make
+```
+
+How to start a sketch
+```
+cd examples_Rpi
+sudo ./<sketch>
+```
+
+This is a derived work from Brian Gladman's AES implementation for byte-oriented
+processors, here's the licence terms:
+
+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+ 1. source code distributions include the above copyright notice, this
+ list of conditions and the following disclaimer;
+
+ 2. binary distributions include the above copyright notice, this list
+ of conditions and the following disclaimer in their documentation;
+
+ 3. the name of the copyright holder is not used to endorse products
+ built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue 09/09/2006
+
+ This is an AES implementation that uses only 8-bit byte operations on the
+ cipher state (there are options to use 32-bit types if available).
+
+ The combination of mix columns and byte substitution used here is based on
+ that developed by Karl Malbrain. His contribution is acknowledged.
+ */
+
+/* This version derived by Mark Tillotson 2012-01-23, tidied up, slimmed down
+ and tailored to 8-bit microcontroller abilities and Arduino datatypes.
+
+ The s-box and inverse s-box were retained as tables (0.5kB PROGMEM) but all
+ the other transformations are coded to save table space. Many efficiency
+ improvments to the routines mix_sub_columns() and inv_mix_sub_columns()
+ (mainly common sub-expression elimination).
+
+ Only the routines with precalculated subkey schedule are retained (together
+ with set_key() - this does however mean each AES object takes 240 bytes of
+ RAM, alas)
+
+ The CBC routines side-effect the iv argument (so that successive calls work
+ together correctly).
+
+ All the encryption and decryption routines work with plain == cipher for
+ in-place encryption, note.
+
+*/
--- /dev/null
+#include <AES.h>
+#include "./printf.h"
+
+AES aes ;
+
+byte *key = (unsigned char*)"0123456789010123";
+
+byte plain[] = "Add NodeAdd NodeAdd NodeAdd NodeAdd Node";
+
+//real iv = iv x2 ex: 01234567 = 0123456701234567
+unsigned long long int my_iv = 36753562;
+
+void setup ()
+{
+ Serial.begin (57600) ;
+ printf_begin();
+ delay(500);
+ printf("\n===testng mode\n") ;
+
+// otfly_test () ;
+// otfly_test256 () ;
+}
+
+void loop ()
+{
+ prekey_test () ;
+ delay(2000);
+}
+
+void prekey (int bits)
+{
+ aes.iv_inc();
+ byte iv [N_BLOCK] ;
+ byte plain_p[48];
+ byte cipher [48] ;
+ byte check [48] ;
+ unsigned long ms = micros ();
+ aes.set_IV(my_iv);
+ aes.get_IV(iv);
+ aes.do_aes_encrypt(plain,41,cipher,key,bits,iv);
+ Serial.print("Encryption took: ");
+ Serial.println(micros() - ms);
+ ms = micros ();
+ aes.set_IV(my_iv);
+ aes.get_IV(iv);
+ aes.do_aes_decrypt(cipher,48,check,key,bits,iv);
+ Serial.print("Decryption took: ");
+ Serial.println(micros() - ms);
+ printf("\n\nPLAIN :");
+ aes.printArray(plain,(bool)true);
+ printf("\nCIPHER:");
+ aes.printArray(cipher,(bool)false);
+ printf("\nCHECK :");
+ aes.printArray(check,(bool)true);
+ printf("\nIV :");
+ aes.printArray(iv,16);
+ printf("\n============================================================\n");
+}
+
+void prekey_test ()
+{
+ prekey (128) ;
+}
--- /dev/null
+Monte Carlo test vectors:
+ http://csrc.nist.gov/groups/STM/cavp/documents/aes/aesmct.zip
+
+(Compare the Monte Carlo output to the ECBMCT128.rsp file)
+
+Known Answer Tests:
+ http://csrc.nist.gov/groups/STM/cavp/documents/aes/KAT_AES.zip
+
+- Compare the other test outputs to
+ ECBVarTxt128.rsp
+ ECBVarKey128.rsp
+ ECBVarTxt192.rsp
+ ECBVarKey192.rsp
+ ECBVarTxt256.rsp
+ ECBVarKey256.rsp
+
--- /dev/null
+AES library test vectors
+Monte Carlo 128 bits
+
+COUNT = 0
+KEY = 139a35422f1d61de3c91787fe0507afd
+PLAINTEXT = b9145a768b7dc489a096b546f43b231f
+CIPHERTEXT = d7c3ffac9031238650901e157364c386
+
+COUNT = 1
+KEY = c459caeebf2c42586c01666a9334b97b
+PLAINTEXT = d7c3ffac9031238650901e157364c386
+CIPHERTEXT = bc3637da2daf8fcf7c68bb28c143a0a4
+
+COUNT = 2
+KEY = 786ffd349283cd971069dd42527719df
+PLAINTEXT = bc3637da2daf8fcf7c68bb28c143a0a4
+CIPHERTEXT = 9c88a8db798f48df1ac4936afa959eac
+
+COUNT = 3
+KEY = e4e755efeb0c85480aad4e28a8e28773
+PLAINTEXT = 9c88a8db798f48df1ac4936afa959eac
+CIPHERTEXT = b87aaa1c76a775d94c2ddf82abe5c66e
+
+COUNT = 4
+KEY = 5c9dfff39dabf091468091aa0307411d
+PLAINTEXT = b87aaa1c76a775d94c2ddf82abe5c66e
+CIPHERTEXT = 79ee212734f14d1bf5a59d46e8c2fa34
+
+COUNT = 5
+KEY = 2573ded4a95abd8ab3250cecebc5bb29
+PLAINTEXT = 79ee212734f14d1bf5a59d46e8c2fa34
+CIPHERTEXT = 09df49135aeb8e373a19fa457ab280a0
+
+COUNT = 6
+KEY = 2cac97c7f3b133bd893cf6a991773b89
+PLAINTEXT = 09df49135aeb8e373a19fa457ab280a0
+CIPHERTEXT = c52263efa6379209d17e87ac250615cb
+
+COUNT = 7
+KEY = e98ef4285586a1b458427105b4712e42
+PLAINTEXT = c52263efa6379209d17e87ac250615cb
+CIPHERTEXT = 336bed017e10a247ee92989862431163
+
+COUNT = 8
+KEY = dae519292b9603f3b6d0e99dd6323f21
+PLAINTEXT = 336bed017e10a247ee92989862431163
+CIPHERTEXT = b13310581ffe5b10aaefdeb8992aec18
+
+COUNT = 9
+KEY = 6bd60971346858e31c3f37254f18d339
+PLAINTEXT = b13310581ffe5b10aaefdeb8992aec18
+CIPHERTEXT = b0eaede3f3eebfef88822a6ede1950b1
+
+COUNT = 10
+KEY = db3ce492c786e70c94bd1d4b91018388
+PLAINTEXT = b0eaede3f3eebfef88822a6ede1950b1
+CIPHERTEXT = 37891fc253b00de13155d5517e1b7890
+
+COUNT = 11
+KEY = ecb5fb509436eaeda5e8c81aef1afb18
+PLAINTEXT = 37891fc253b00de13155d5517e1b7890
+CIPHERTEXT = 8f574c85fa44af2d43c95ee5f627fc9d
+
+COUNT = 12
+KEY = 63e2b7d56e7245c0e62196ff193d0785
+PLAINTEXT = 8f574c85fa44af2d43c95ee5f627fc9d
+CIPHERTEXT = 6c0af6709225f328a0225b2280efa3e3
+
+COUNT = 13
+KEY = 0fe841a5fc57b6e84603cddd99d2a466
+PLAINTEXT = 6c0af6709225f328a0225b2280efa3e3
+CIPHERTEXT = e2dc36073fe192e712373a8702e8adce
+
+COUNT = 14
+KEY = ed3477a2c3b6240f5434f75a9b3a09a8
+PLAINTEXT = e2dc36073fe192e712373a8702e8adce
+CIPHERTEXT = 1e91d1e1f82f1d320186210a792f7ba1
+
+COUNT = 15
+KEY = f3a5a6433b99393d55b2d650e2157209
+PLAINTEXT = 1e91d1e1f82f1d320186210a792f7ba1
+CIPHERTEXT = 228eac74166da261d7fa83f43d9ddd2f
+
+COUNT = 16
+KEY = d12b0a372df49b5c824855a4df88af26
+PLAINTEXT = 228eac74166da261d7fa83f43d9ddd2f
+CIPHERTEXT = 25d0de6a894361a1b83d5fa2fd607f26
+
+COUNT = 17
+KEY = f4fbd45da4b7fafd3a750a0622e8d000
+PLAINTEXT = 25d0de6a894361a1b83d5fa2fd607f26
+CIPHERTEXT = 36095dc3e659ec50ca7f6f8207d20031
+
+COUNT = 18
+KEY = c2f2899e42ee16adf00a6584253ad031
+PLAINTEXT = 36095dc3e659ec50ca7f6f8207d20031
+CIPHERTEXT = 8dbfe965078468875d86145164c4ab4f
+
+COUNT = 19
+KEY = 4f4d60fb456a7e2aad8c71d541fe7b7e
+PLAINTEXT = 8dbfe965078468875d86145164c4ab4f
+CIPHERTEXT = 4032bb8137d4b9eb93644359a995bb4e
+
+COUNT = 20
+KEY = 0f7fdb7a72bec7c13ee8328ce86bc030
+PLAINTEXT = 4032bb8137d4b9eb93644359a995bb4e
+CIPHERTEXT = 85308aa92c625a25bd5f4a40375c6baa
+
+COUNT = 21
+KEY = 8a4f51d35edc9de483b778ccdf37ab9a
+PLAINTEXT = 85308aa92c625a25bd5f4a40375c6baa
+CIPHERTEXT = 73283fc59e04e80a867e478d97a3f388
+
+COUNT = 22
+KEY = f9676e16c0d875ee05c93f4148945812
+PLAINTEXT = 73283fc59e04e80a867e478d97a3f388
+CIPHERTEXT = 418c1fe377e4ef9832f20286b167f916
+
+COUNT = 23
+KEY = b8eb71f5b73c9a76373b3dc7f9f3a104
+PLAINTEXT = 418c1fe377e4ef9832f20286b167f916
+CIPHERTEXT = 60ad1341525e67cffdd68ff671253c77
+
+COUNT = 24
+KEY = d84662b4e562fdb9caedb23188d69d73
+PLAINTEXT = 60ad1341525e67cffdd68ff671253c77
+CIPHERTEXT = 4edf6e01a76de6153d17713a49d5b028
+
+COUNT = 25
+KEY = 96990cb5420f1bacf7fac30bc1032d5b
+PLAINTEXT = 4edf6e01a76de6153d17713a49d5b028
+CIPHERTEXT = 2c85ebf9e3d80596f78712df56ac77cd
+
+COUNT = 26
+KEY = ba1ce74ca1d71e3a007dd1d497af5a96
+PLAINTEXT = 2c85ebf9e3d80596f78712df56ac77cd
+CIPHERTEXT = 8fc8ef9ab7462712977e87c741795ece
+
+COUNT = 27
+KEY = 35d408d61691392897035613d6d60458
+PLAINTEXT = 8fc8ef9ab7462712977e87c741795ece
+CIPHERTEXT = 37e9ac800cfb19133b4e9b0c418ca098
+
+COUNT = 28
+KEY = 023da4561a6a203bac4dcd1f975aa4c0
+PLAINTEXT = 37e9ac800cfb19133b4e9b0c418ca098
+CIPHERTEXT = cb7cd7619caa605e45f95f5b31a85495
+
+COUNT = 29
+KEY = c941733786c04065e9b49244a6f2f055
+PLAINTEXT = cb7cd7619caa605e45f95f5b31a85495
+CIPHERTEXT = 6e265e5fd030847b8841bf6652996392
+
+COUNT = 30
+KEY = a7672d6856f0c41e61f52d22f46b93c7
+PLAINTEXT = 6e265e5fd030847b8841bf6652996392
+CIPHERTEXT = 5c9a7d2ce1c86f0b3425b3b6aae108e0
+
+COUNT = 31
+KEY = fbfd5044b738ab1555d09e945e8a9b27
+PLAINTEXT = 5c9a7d2ce1c86f0b3425b3b6aae108e0
+CIPHERTEXT = c911dee5ff318a7e799f92daadcb3d9a
+
+COUNT = 32
+KEY = 32ec8ea14809216b2c4f0c4ef341a6bd
+PLAINTEXT = c911dee5ff318a7e799f92daadcb3d9a
+CIPHERTEXT = 7a3afdf10410f1c47c7d928d4a8d432a
+
+COUNT = 33
+KEY = 48d673504c19d0af50329ec3b9cce597
+PLAINTEXT = 7a3afdf10410f1c47c7d928d4a8d432a
+CIPHERTEXT = c681b7b6d3ec9dc91012e3b7427c67ad
+
+COUNT = 34
+KEY = 8e57c4e69ff54d6640207d74fbb0823a
+PLAINTEXT = c681b7b6d3ec9dc91012e3b7427c67ad
+CIPHERTEXT = cd3f84bbe958536d502065eb37ae10b4
+
+COUNT = 35
+KEY = 4368405d76ad1e0b1000189fcc1e928e
+PLAINTEXT = cd3f84bbe958536d502065eb37ae10b4
+CIPHERTEXT = 879db797e686b9116c25c07f4ae67593
+
+COUNT = 36
+KEY = c4f5f7ca902ba71a7c25d8e086f8e71d
+PLAINTEXT = 879db797e686b9116c25c07f4ae67593
+CIPHERTEXT = 5959ebd7a1167713429eda69538c536b
+
+COUNT = 37
+KEY = 9dac1c1d313dd0093ebb0289d574b476
+PLAINTEXT = 5959ebd7a1167713429eda69538c536b
+CIPHERTEXT = f57101d7fa19f97a31d60b276312717c
+
+COUNT = 38
+KEY = 68dd1dcacb2429730f6d09aeb666c50a
+PLAINTEXT = f57101d7fa19f97a31d60b276312717c
+CIPHERTEXT = 6dfbbc2b147568c55adbfdc3c706edb0
+
+COUNT = 39
+KEY = 0526a1e1df5141b655b6f46d716028ba
+PLAINTEXT = 6dfbbc2b147568c55adbfdc3c706edb0
+CIPHERTEXT = 9c4ea9002306d75e7b0f03e2a72b7a1d
+
+COUNT = 40
+KEY = 996808e1fc5796e82eb9f78fd64b52a7
+PLAINTEXT = 9c4ea9002306d75e7b0f03e2a72b7a1d
+CIPHERTEXT = cb9975336cc05f0114f26bde4cc84f8d
+
+COUNT = 41
+KEY = 52f17dd29097c9e93a4b9c519a831d2a
+PLAINTEXT = cb9975336cc05f0114f26bde4cc84f8d
+CIPHERTEXT = 902c4250cff110d792938e8dcd534cf0
+
+COUNT = 42
+KEY = c2dd3f825f66d93ea8d812dc57d051da
+PLAINTEXT = 902c4250cff110d792938e8dcd534cf0
+CIPHERTEXT = 140242f195ef2ef7f6ee23574c071311
+
+COUNT = 43
+KEY = d6df7d73ca89f7c95e36318b1bd742cb
+PLAINTEXT = 140242f195ef2ef7f6ee23574c071311
+CIPHERTEXT = 3c6d4ffafde866f1e994480c47d20a04
+
+COUNT = 44
+KEY = eab2328937619138b7a279875c0548cf
+PLAINTEXT = 3c6d4ffafde866f1e994480c47d20a04
+CIPHERTEXT = 1ca04a21addc38ef8bfc8989d3d6b33b
+
+COUNT = 45
+KEY = f61278a89abda9d73c5ef00e8fd3fbf4
+PLAINTEXT = 1ca04a21addc38ef8bfc8989d3d6b33b
+CIPHERTEXT = bb8875ee3c3c8c0987b1c20f999028e9
+
+COUNT = 46
+KEY = 4d9a0d46a68125debbef32011643d31d
+PLAINTEXT = bb8875ee3c3c8c0987b1c20f999028e9
+CIPHERTEXT = 9d33724d80a76f2033a37a851403ef28
+
+COUNT = 47
+KEY = d0a97f0b26264afe884c488402403c35
+PLAINTEXT = 9d33724d80a76f2033a37a851403ef28
+CIPHERTEXT = 4c92fe152d16da8ea59b9f29c75f20ff
+
+COUNT = 48
+KEY = 9c3b811e0b3090702dd7d7adc51f1cca
+PLAINTEXT = 4c92fe152d16da8ea59b9f29c75f20ff
+CIPHERTEXT = 659c76f73032b0192b281034b6a99a3f
+
+COUNT = 49
+KEY = f9a7f7e93b02206906ffc79973b686f5
+PLAINTEXT = 659c76f73032b0192b281034b6a99a3f
+CIPHERTEXT = 5d296637697ccad84fc77936a31c2655
+
+COUNT = 50
+KEY = a48e91de527eeab14938beafd0aaa0a0
+PLAINTEXT = 5d296637697ccad84fc77936a31c2655
+CIPHERTEXT = a72a596a030d5541bc4d0fc739491d5b
+
+COUNT = 51
+KEY = 03a4c8b45173bff0f575b168e9e3bdfb
+PLAINTEXT = a72a596a030d5541bc4d0fc739491d5b
+CIPHERTEXT = 5f5ec53c91225717fcba470688dfa364
+
+COUNT = 52
+KEY = 5cfa0d88c051e8e709cff66e613c1e9f
+PLAINTEXT = 5f5ec53c91225717fcba470688dfa364
+CIPHERTEXT = 5719cb14eba820c0d51109a0c7a4154f
+
+COUNT = 53
+KEY = 0be3c69c2bf9c827dcdeffcea6980bd0
+PLAINTEXT = 5719cb14eba820c0d51109a0c7a4154f
+CIPHERTEXT = 3abd186712a9def73b6312b5300f02af
+
+COUNT = 54
+KEY = 315edefb395016d0e7bded7b9697097f
+PLAINTEXT = 3abd186712a9def73b6312b5300f02af
+CIPHERTEXT = b1e90c8c0d4c9651a6de7f52a63ac456
+
+COUNT = 55
+KEY = 80b7d277341c80814163922930adcd29
+PLAINTEXT = b1e90c8c0d4c9651a6de7f52a63ac456
+CIPHERTEXT = 5d26e33aae1441554034c77bde451679
+
+COUNT = 56
+KEY = dd91314d9a08c1d401575552eee8db50
+PLAINTEXT = 5d26e33aae1441554034c77bde451679
+CIPHERTEXT = 93e44cdce14803544a53bc5b520c156f
+
+COUNT = 57
+KEY = 4e757d917b40c2804b04e909bce4ce3f
+PLAINTEXT = 93e44cdce14803544a53bc5b520c156f
+CIPHERTEXT = 8ee3b6fd953b441043f69f3747e4cf63
+
+COUNT = 58
+KEY = c096cb6cee7b869008f2763efb00015c
+PLAINTEXT = 8ee3b6fd953b441043f69f3747e4cf63
+CIPHERTEXT = cb2f545970200630e5145f817a013807
+
+COUNT = 59
+KEY = 0bb99f359e5b80a0ede629bf8101395b
+PLAINTEXT = cb2f545970200630e5145f817a013807
+CIPHERTEXT = 50047276451ce19cb14d8d2ef0b3851b
+
+COUNT = 60
+KEY = 5bbded43db47613c5caba49171b2bc40
+PLAINTEXT = 50047276451ce19cb14d8d2ef0b3851b
+CIPHERTEXT = d243791dde33c2a4333ef4dcbcadbd3a
+
+COUNT = 61
+KEY = 89fe945e0574a3986f95504dcd1f017a
+PLAINTEXT = d243791dde33c2a4333ef4dcbcadbd3a
+CIPHERTEXT = 343181860092a5e33c2e1c441a9f6804
+
+COUNT = 62
+KEY = bdcf15d805e6067b53bb4c09d780697e
+PLAINTEXT = 343181860092a5e33c2e1c441a9f6804
+CIPHERTEXT = 4e7cdd553d732909e25a13a521e04078
+
+COUNT = 63
+KEY = f3b3c88d38952f72b1e15facf6602906
+PLAINTEXT = 4e7cdd553d732909e25a13a521e04078
+CIPHERTEXT = 9c16f3fda49bb6a2b6d76a6696bd768f
+
+COUNT = 64
+KEY = 6fa53b709c0e99d0073635ca60dd5f89
+PLAINTEXT = 9c16f3fda49bb6a2b6d76a6696bd768f
+CIPHERTEXT = 9eb63f9099123591a4ca7aa0fff55a49
+
+COUNT = 65
+KEY = f11304e0051cac41a3fc4f6a9f2805c0
+PLAINTEXT = 9eb63f9099123591a4ca7aa0fff55a49
+CIPHERTEXT = aa6a9e40aad692550b7c87b92b205af0
+
+COUNT = 66
+KEY = 5b799aa0afca3e14a880c8d3b4085f30
+PLAINTEXT = aa6a9e40aad692550b7c87b92b205af0
+CIPHERTEXT = ae92c267f38b9b4623df36523bb739b6
+
+COUNT = 67
+KEY = f5eb58c75c41a5528b5ffe818fbf6686
+PLAINTEXT = ae92c267f38b9b4623df36523bb739b6
+CIPHERTEXT = 39c0de843767dfa2d563c0632405d595
+
+COUNT = 68
+KEY = cc2b86436b267af05e3c3ee2abbab313
+PLAINTEXT = 39c0de843767dfa2d563c0632405d595
+CIPHERTEXT = 80a9445be75373b07476608feb1f1c7b
+
+COUNT = 69
+KEY = 4c82c2188c7509402a4a5e6d40a5af68
+PLAINTEXT = 80a9445be75373b07476608feb1f1c7b
+CIPHERTEXT = 5306f5a77e42d9f4cee8f134ba1448c6
+
+COUNT = 70
+KEY = 1f8437bff237d0b4e4a2af59fab1e7ae
+PLAINTEXT = 5306f5a77e42d9f4cee8f134ba1448c6
+CIPHERTEXT = 8db0c3fba7dc797cd175d97503759260
+
+COUNT = 71
+KEY = 9234f44455eba9c835d7762cf9c475ce
+PLAINTEXT = 8db0c3fba7dc797cd175d97503759260
+CIPHERTEXT = 04fcb0c77ae0c98d2afb178ab2c2b02d
+
+COUNT = 72
+KEY = 96c844832f0b60451f2c61a64b06c5e3
+PLAINTEXT = 04fcb0c77ae0c98d2afb178ab2c2b02d
+CIPHERTEXT = 1a156581b3557078971cc6877a3d9339
+
+COUNT = 73
+KEY = 8cdd21029c5e103d8830a721313b56da
+PLAINTEXT = 1a156581b3557078971cc6877a3d9339
+CIPHERTEXT = e47087289290fa2b6734eeaab2fc815d
+
+COUNT = 74
+KEY = 68ada62a0eceea16ef04498b83c7d787
+PLAINTEXT = e47087289290fa2b6734eeaab2fc815d
+CIPHERTEXT = 00ce641525020d35244e2227287b2a20
+
+COUNT = 75
+KEY = 6863c23f2bcce723cb4a6bacabbcfda7
+PLAINTEXT = 00ce641525020d35244e2227287b2a20
+CIPHERTEXT = ecf623cef1e420d0994070c078592c97
+
+COUNT = 76
+KEY = 8495e1f1da28c7f3520a1b6cd3e5d130
+PLAINTEXT = ecf623cef1e420d0994070c078592c97
+CIPHERTEXT = 256c8f28df4a286fb05514fcfa8cbcaf
+
+COUNT = 77
+KEY = a1f96ed90562ef9ce25f0f9029696d9f
+PLAINTEXT = 256c8f28df4a286fb05514fcfa8cbcaf
+CIPHERTEXT = fd4aed4b5a2b8edefe3cc2aef6ecd298
+
+COUNT = 78
+KEY = 5cb383925f4961421c63cd3edf85bf07
+PLAINTEXT = fd4aed4b5a2b8edefe3cc2aef6ecd298
+CIPHERTEXT = dfe0e571f77f0b46c52f003e774918ac
+
+COUNT = 79
+KEY = 835366e3a8366a04d94ccd00a8cca7ab
+PLAINTEXT = dfe0e571f77f0b46c52f003e774918ac
+CIPHERTEXT = e421fbeb4c23745b97578162f89e68fc
+
+COUNT = 80
+KEY = 67729d08e4151e5f4e1b4c625052cf57
+PLAINTEXT = e421fbeb4c23745b97578162f89e68fc
+CIPHERTEXT = c38c0bbde031d1a79438f79ff7cc68a5
+
+COUNT = 81
+KEY = a4fe96b50424cff8da23bbfda79ea7f2
+PLAINTEXT = c38c0bbde031d1a79438f79ff7cc68a5
+CIPHERTEXT = 86113133968aa3052709875bf033d804
+
+COUNT = 82
+KEY = 22efa78692ae6cfdfd2a3ca657ad7ff6
+PLAINTEXT = 86113133968aa3052709875bf033d804
+CIPHERTEXT = fd706bef1bf30c8d1e95543b75629e02
+
+COUNT = 83
+KEY = df9fcc69895d6070e3bf689d22cfe1f4
+PLAINTEXT = fd706bef1bf30c8d1e95543b75629e02
+CIPHERTEXT = 9a5bbb6125152f1352b10e1c1a172aa6
+
+COUNT = 84
+KEY = 45c47708ac484f63b10e668138d8cb52
+PLAINTEXT = 9a5bbb6125152f1352b10e1c1a172aa6
+CIPHERTEXT = 3ee69736488c51fa72784aa263618f45
+
+COUNT = 85
+KEY = 7b22e03ee4c41e99c3762c235bb94417
+PLAINTEXT = 3ee69736488c51fa72784aa263618f45
+CIPHERTEXT = fc66daa246ebcc320c7c89b599014633
+
+COUNT = 86
+KEY = 87443a9ca22fd2abcf0aa596c2b80224
+PLAINTEXT = fc66daa246ebcc320c7c89b599014633
+CIPHERTEXT = 35645885ed205d67e5caeff26646c38c
+
+COUNT = 87
+KEY = b22062194f0f8fcc2ac04a64a4fec1a8
+PLAINTEXT = 35645885ed205d67e5caeff26646c38c
+CIPHERTEXT = daeaa866aa4eacdb752caccb2c0ae6c1
+
+COUNT = 88
+KEY = 68caca7fe54123175fece6af88f42769
+PLAINTEXT = daeaa866aa4eacdb752caccb2c0ae6c1
+CIPHERTEXT = 29e88b1ae615fcd06b09e767459d6089
+
+COUNT = 89
+KEY = 412241650354dfc734e501c8cd6947e0
+PLAINTEXT = 29e88b1ae615fcd06b09e767459d6089
+CIPHERTEXT = 63470bff052e7f5c7a735cc2e6eb61ac
+
+COUNT = 90
+KEY = 22654a9a067aa09b4e965d0a2b82264c
+PLAINTEXT = 63470bff052e7f5c7a735cc2e6eb61ac
+CIPHERTEXT = f4fa6a3549cd2b33af9cac134d7b1402
+
+COUNT = 91
+KEY = d69f20af4fb78ba8e10af11966f9324e
+PLAINTEXT = f4fa6a3549cd2b33af9cac134d7b1402
+CIPHERTEXT = 5b22a82ccbae9b9c75f797e74e6da53d
+
+COUNT = 92
+KEY = 8dbd88838419103494fd66fe28949773
+PLAINTEXT = 5b22a82ccbae9b9c75f797e74e6da53d
+CIPHERTEXT = 87b51692f8f28743bd8dc843276f351a
+
+COUNT = 93
+KEY = 0a089e117ceb97772970aebd0ffba269
+PLAINTEXT = 87b51692f8f28743bd8dc843276f351a
+CIPHERTEXT = 150fb2180704a7623a1fab8bf17fba18
+
+COUNT = 94
+KEY = 1f072c097bef3015136f0536fe841871
+PLAINTEXT = 150fb2180704a7623a1fab8bf17fba18
+CIPHERTEXT = 8088874e7f3f09a98fd3f0a59f2a0b4b
+
+COUNT = 95
+KEY = 9f8fab4704d039bc9cbcf59361ae133a
+PLAINTEXT = 8088874e7f3f09a98fd3f0a59f2a0b4b
+CIPHERTEXT = 08e02c091057d81c05d917ea5c07cdd0
+
+COUNT = 96
+KEY = 976f874e1487e1a09965e2793da9deea
+PLAINTEXT = 08e02c091057d81c05d917ea5c07cdd0
+CIPHERTEXT = b9636b3e2752694c3685872fd0a9a0ea
+
+COUNT = 97
+KEY = 2e0cec7033d588ecafe06556ed007e00
+PLAINTEXT = b9636b3e2752694c3685872fd0a9a0ea
+CIPHERTEXT = 2610dae2b64d74a8cbb4f43fa2d0a603
+
+COUNT = 98
+KEY = 081c36928598fc44645491694fd0d803
+PLAINTEXT = 2610dae2b64d74a8cbb4f43fa2d0a603
+CIPHERTEXT = 9cc994eda697fb5545eaa502b2a30fd3
+
+COUNT = 99
+KEY = 94d5a27f230f071121be346bfd73d7d0
+PLAINTEXT = 9cc994eda697fb5545eaa502b2a30fd3
+CIPHERTEXT = fb2649694783b551eacd9d5db6126d47
+
+
+ECB Varying Plaintext 128 bits
+
+COUNT = 0
+KEY = 00000000000000000000000000000000
+PLAINTEXT = 80000000000000000000000000000000
+CIPHERTEXT = 3ad78e726c1ec02b7ebfe92b23d9ec34
+
+COUNT = 1
+KEY = 00000000000000000000000000000000
+PLAINTEXT = c0000000000000000000000000000000
+CIPHERTEXT = aae5939c8efdf2f04e60b9fe7117b2c2
+
+COUNT = 2
+KEY = 00000000000000000000000000000000
+PLAINTEXT = e0000000000000000000000000000000
+CIPHERTEXT = f031d4d74f5dcbf39daaf8ca3af6e527
+
+COUNT = 3
+KEY = 00000000000000000000000000000000
+PLAINTEXT = f0000000000000000000000000000000
+CIPHERTEXT = 96d9fd5cc4f07441727df0f33e401a36
+
+COUNT = 4
+KEY = 00000000000000000000000000000000
+PLAINTEXT = f8000000000000000000000000000000
+CIPHERTEXT = 30ccdb044646d7e1f3ccea3dca08b8c0
+
+COUNT = 5
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fc000000000000000000000000000000
+CIPHERTEXT = 16ae4ce5042a67ee8e177b7c587ecc82
+
+COUNT = 6
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fe000000000000000000000000000000
+CIPHERTEXT = b6da0bb11a23855d9c5cb1b4c6412e0a
+
+COUNT = 7
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ff000000000000000000000000000000
+CIPHERTEXT = db4f1aa530967d6732ce4715eb0ee24b
+
+COUNT = 8
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ff800000000000000000000000000000
+CIPHERTEXT = a81738252621dd180a34f3455b4baa2f
+
+COUNT = 9
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffc00000000000000000000000000000
+CIPHERTEXT = 77e2b508db7fd89234caf7939ee5621a
+
+COUNT = 10
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffe00000000000000000000000000000
+CIPHERTEXT = b8499c251f8442ee13f0933b688fcd19
+
+COUNT = 11
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fff00000000000000000000000000000
+CIPHERTEXT = 965135f8a81f25c9d630b17502f68e53
+
+COUNT = 12
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fff80000000000000000000000000000
+CIPHERTEXT = 8b87145a01ad1c6cede995ea3670454f
+
+COUNT = 13
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffc0000000000000000000000000000
+CIPHERTEXT = 8eae3b10a0c8ca6d1d3b0fa61e56b0b2
+
+COUNT = 14
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffe0000000000000000000000000000
+CIPHERTEXT = 64b4d629810fda6bafdf08f3b0d8d2c5
+
+COUNT = 15
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffff0000000000000000000000000000
+CIPHERTEXT = d7e5dbd3324595f8fdc7d7c571da6c2a
+
+COUNT = 16
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffff8000000000000000000000000000
+CIPHERTEXT = f3f72375264e167fca9de2c1527d9606
+
+COUNT = 17
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffc000000000000000000000000000
+CIPHERTEXT = 8ee79dd4f401ff9b7ea945d86666c13b
+
+COUNT = 18
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffe000000000000000000000000000
+CIPHERTEXT = dd35cea2799940b40db3f819cb94c08b
+
+COUNT = 19
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffff000000000000000000000000000
+CIPHERTEXT = 6941cb6b3e08c2b7afa581ebdd607b87
+
+COUNT = 20
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffff800000000000000000000000000
+CIPHERTEXT = 2c20f439f6bb097b29b8bd6d99aad799
+
+COUNT = 21
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffc00000000000000000000000000
+CIPHERTEXT = 625d01f058e565f77ae86378bd2c49b3
+
+COUNT = 22
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffe00000000000000000000000000
+CIPHERTEXT = c0b5fd98190ef45fbb4301438d095950
+
+COUNT = 23
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffff00000000000000000000000000
+CIPHERTEXT = 13001ff5d99806efd25da34f56be854b
+
+COUNT = 24
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffff80000000000000000000000000
+CIPHERTEXT = 3b594c60f5c8277a5113677f94208d82
+
+COUNT = 25
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffc0000000000000000000000000
+CIPHERTEXT = e9c0fc1818e4aa46bd2e39d638f89e05
+
+COUNT = 26
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffe0000000000000000000000000
+CIPHERTEXT = f8023ee9c3fdc45a019b4e985c7e1a54
+
+COUNT = 27
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffff0000000000000000000000000
+CIPHERTEXT = 35f40182ab4662f3023baec1ee796b57
+
+COUNT = 28
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffff8000000000000000000000000
+CIPHERTEXT = 3aebbad7303649b4194a6945c6cc3694
+
+COUNT = 29
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffc000000000000000000000000
+CIPHERTEXT = a2124bea53ec2834279bed7f7eb0f938
+
+COUNT = 30
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffe000000000000000000000000
+CIPHERTEXT = b9fb4399fa4facc7309e14ec98360b0a
+
+COUNT = 31
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffff000000000000000000000000
+CIPHERTEXT = c26277437420c5d634f715aea81a9132
+
+COUNT = 32
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffff800000000000000000000000
+CIPHERTEXT = 171a0e1b2dd424f0e089af2c4c10f32f
+
+COUNT = 33
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffc00000000000000000000000
+CIPHERTEXT = 7cadbe402d1b208fe735edce00aee7ce
+
+COUNT = 34
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffe00000000000000000000000
+CIPHERTEXT = 43b02ff929a1485af6f5c6d6558baa0f
+
+COUNT = 35
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffff00000000000000000000000
+CIPHERTEXT = 092faacc9bf43508bf8fa8613ca75dea
+
+COUNT = 36
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffff80000000000000000000000
+CIPHERTEXT = cb2bf8280f3f9742c7ed513fe802629c
+
+COUNT = 37
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffc0000000000000000000000
+CIPHERTEXT = 215a41ee442fa992a6e323986ded3f68
+
+COUNT = 38
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffe0000000000000000000000
+CIPHERTEXT = f21e99cf4f0f77cea836e11a2fe75fb1
+
+COUNT = 39
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffff0000000000000000000000
+CIPHERTEXT = 95e3a0ca9079e646331df8b4e70d2cd6
+
+COUNT = 40
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffff8000000000000000000000
+CIPHERTEXT = 4afe7f120ce7613f74fc12a01a828073
+
+COUNT = 41
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffc000000000000000000000
+CIPHERTEXT = 827f000e75e2c8b9d479beed913fe678
+
+COUNT = 42
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffe000000000000000000000
+CIPHERTEXT = 35830c8e7aaefe2d30310ef381cbf691
+
+COUNT = 43
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffff000000000000000000000
+CIPHERTEXT = 191aa0f2c8570144f38657ea4085ebe5
+
+COUNT = 44
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffff800000000000000000000
+CIPHERTEXT = 85062c2c909f15d9269b6c18ce99c4f0
+
+COUNT = 45
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffc00000000000000000000
+CIPHERTEXT = 678034dc9e41b5a560ed239eeab1bc78
+
+COUNT = 46
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffe00000000000000000000
+CIPHERTEXT = c2f93a4ce5ab6d5d56f1b93cf19911c1
+
+COUNT = 47
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffff00000000000000000000
+CIPHERTEXT = 1c3112bcb0c1dcc749d799743691bf82
+
+COUNT = 48
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffff80000000000000000000
+CIPHERTEXT = 00c55bd75c7f9c881989d3ec1911c0d4
+
+COUNT = 49
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffc0000000000000000000
+CIPHERTEXT = ea2e6b5ef182b7dff3629abd6a12045f
+
+COUNT = 50
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffe0000000000000000000
+CIPHERTEXT = 22322327e01780b17397f24087f8cc6f
+
+COUNT = 51
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffff0000000000000000000
+CIPHERTEXT = c9cacb5cd11692c373b2411768149ee7
+
+COUNT = 52
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffff8000000000000000000
+CIPHERTEXT = a18e3dbbca577860dab6b80da3139256
+
+COUNT = 53
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffc000000000000000000
+CIPHERTEXT = 79b61c37bf328ecca8d743265a3d425c
+
+COUNT = 54
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffe000000000000000000
+CIPHERTEXT = d2d99c6bcc1f06fda8e27e8ae3f1ccc7
+
+COUNT = 55
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffff000000000000000000
+CIPHERTEXT = 1bfd4b91c701fd6b61b7f997829d663b
+
+COUNT = 56
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffff800000000000000000
+CIPHERTEXT = 11005d52f25f16bdc9545a876a63490a
+
+COUNT = 57
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffc00000000000000000
+CIPHERTEXT = 3a4d354f02bb5a5e47d39666867f246a
+
+COUNT = 58
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffe00000000000000000
+CIPHERTEXT = d451b8d6e1e1a0ebb155fbbf6e7b7dc3
+
+COUNT = 59
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffff00000000000000000
+CIPHERTEXT = 6898d4f42fa7ba6a10ac05e87b9f2080
+
+COUNT = 60
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffff80000000000000000
+CIPHERTEXT = b611295e739ca7d9b50f8e4c0e754a3f
+
+COUNT = 61
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffc0000000000000000
+CIPHERTEXT = 7d33fc7d8abe3ca1936759f8f5deaf20
+
+COUNT = 62
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffe0000000000000000
+CIPHERTEXT = 3b5e0f566dc96c298f0c12637539b25c
+
+COUNT = 63
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffff0000000000000000
+CIPHERTEXT = f807c3e7985fe0f5a50e2cdb25c5109e
+
+COUNT = 64
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffff8000000000000000
+CIPHERTEXT = 41f992a856fb278b389a62f5d274d7e9
+
+COUNT = 65
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffc000000000000000
+CIPHERTEXT = 10d3ed7a6fe15ab4d91acbc7d0767ab1
+
+COUNT = 66
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffe000000000000000
+CIPHERTEXT = 21feecd45b2e675973ac33bf0c5424fc
+
+COUNT = 67
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffff000000000000000
+CIPHERTEXT = 1480cb3955ba62d09eea668f7c708817
+
+COUNT = 68
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffff800000000000000
+CIPHERTEXT = 66404033d6b72b609354d5496e7eb511
+
+COUNT = 69
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffc00000000000000
+CIPHERTEXT = 1c317a220a7d700da2b1e075b00266e1
+
+COUNT = 70
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffe00000000000000
+CIPHERTEXT = ab3b89542233f1271bf8fd0c0f403545
+
+COUNT = 71
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffff00000000000000
+CIPHERTEXT = d93eae966fac46dca927d6b114fa3f9e
+
+COUNT = 72
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffff80000000000000
+CIPHERTEXT = 1bdec521316503d9d5ee65df3ea94ddf
+
+COUNT = 73
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffc0000000000000
+CIPHERTEXT = eef456431dea8b4acf83bdae3717f75f
+
+COUNT = 74
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffe0000000000000
+CIPHERTEXT = 06f2519a2fafaa596bfef5cfa15c21b9
+
+COUNT = 75
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffff0000000000000
+CIPHERTEXT = 251a7eac7e2fe809e4aa8d0d7012531a
+
+COUNT = 76
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffff8000000000000
+CIPHERTEXT = 3bffc16e4c49b268a20f8d96a60b4058
+
+COUNT = 77
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffc000000000000
+CIPHERTEXT = e886f9281999c5bb3b3e8862e2f7c988
+
+COUNT = 78
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffe000000000000
+CIPHERTEXT = 563bf90d61beef39f48dd625fcef1361
+
+COUNT = 79
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffff000000000000
+CIPHERTEXT = 4d37c850644563c69fd0acd9a049325b
+
+COUNT = 80
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffff800000000000
+CIPHERTEXT = b87c921b91829ef3b13ca541ee1130a6
+
+COUNT = 81
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffc00000000000
+CIPHERTEXT = 2e65eb6b6ea383e109accce8326b0393
+
+COUNT = 82
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffe00000000000
+CIPHERTEXT = 9ca547f7439edc3e255c0f4d49aa8990
+
+COUNT = 83
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffff00000000000
+CIPHERTEXT = a5e652614c9300f37816b1f9fd0c87f9
+
+COUNT = 84
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffff80000000000
+CIPHERTEXT = 14954f0b4697776f44494fe458d814ed
+
+COUNT = 85
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffc0000000000
+CIPHERTEXT = 7c8d9ab6c2761723fe42f8bb506cbcf7
+
+COUNT = 86
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffe0000000000
+CIPHERTEXT = db7e1932679fdd99742aab04aa0d5a80
+
+COUNT = 87
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffff0000000000
+CIPHERTEXT = 4c6a1c83e568cd10f27c2d73ded19c28
+
+COUNT = 88
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffff8000000000
+CIPHERTEXT = 90ecbe6177e674c98de412413f7ac915
+
+COUNT = 89
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffc000000000
+CIPHERTEXT = 90684a2ac55fe1ec2b8ebd5622520b73
+
+COUNT = 90
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffe000000000
+CIPHERTEXT = 7472f9a7988607ca79707795991035e6
+
+COUNT = 91
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffff000000000
+CIPHERTEXT = 56aff089878bf3352f8df172a3ae47d8
+
+COUNT = 92
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffff800000000
+CIPHERTEXT = 65c0526cbe40161b8019a2a3171abd23
+
+COUNT = 93
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffc00000000
+CIPHERTEXT = 377be0be33b4e3e310b4aabda173f84f
+
+COUNT = 94
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffe00000000
+CIPHERTEXT = 9402e9aa6f69de6504da8d20c4fcaa2f
+
+COUNT = 95
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffff00000000
+CIPHERTEXT = 123c1f4af313ad8c2ce648b2e71fb6e1
+
+COUNT = 96
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffff80000000
+CIPHERTEXT = 1ffc626d30203dcdb0019fb80f726cf4
+
+COUNT = 97
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffc0000000
+CIPHERTEXT = 76da1fbe3a50728c50fd2e621b5ad885
+
+COUNT = 98
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffe0000000
+CIPHERTEXT = 082eb8be35f442fb52668e16a591d1d6
+
+COUNT = 99
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffff0000000
+CIPHERTEXT = e656f9ecf5fe27ec3e4a73d00c282fb3
+
+COUNT = 100
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffff8000000
+CIPHERTEXT = 2ca8209d63274cd9a29bb74bcd77683a
+
+COUNT = 101
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffc000000
+CIPHERTEXT = 79bf5dce14bb7dd73a8e3611de7ce026
+
+COUNT = 102
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffe000000
+CIPHERTEXT = 3c849939a5d29399f344c4a0eca8a576
+
+COUNT = 103
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffff000000
+CIPHERTEXT = ed3c0a94d59bece98835da7aa4f07ca2
+
+COUNT = 104
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffff800000
+CIPHERTEXT = 63919ed4ce10196438b6ad09d99cd795
+
+COUNT = 105
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffc00000
+CIPHERTEXT = 7678f3a833f19fea95f3c6029e2bc610
+
+COUNT = 106
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffe00000
+CIPHERTEXT = 3aa426831067d36b92be7c5f81c13c56
+
+COUNT = 107
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffff00000
+CIPHERTEXT = 9272e2d2cdd11050998c845077a30ea0
+
+COUNT = 108
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffff80000
+CIPHERTEXT = 088c4b53f5ec0ff814c19adae7f6246c
+
+COUNT = 109
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffc0000
+CIPHERTEXT = 4010a5e401fdf0a0354ddbcc0d012b17
+
+COUNT = 110
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffe0000
+CIPHERTEXT = a87a385736c0a6189bd6589bd8445a93
+
+COUNT = 111
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffff0000
+CIPHERTEXT = 545f2b83d9616dccf60fa9830e9cd287
+
+COUNT = 112
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffff8000
+CIPHERTEXT = 4b706f7f92406352394037a6d4f4688d
+
+COUNT = 113
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffc000
+CIPHERTEXT = b7972b3941c44b90afa7b264bfba7387
+
+COUNT = 114
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffe000
+CIPHERTEXT = 6f45732cf10881546f0fd23896d2bb60
+
+COUNT = 115
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffff000
+CIPHERTEXT = 2e3579ca15af27f64b3c955a5bfc30ba
+
+COUNT = 116
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffff800
+CIPHERTEXT = 34a2c5a91ae2aec99b7d1b5fa6780447
+
+COUNT = 117
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffc00
+CIPHERTEXT = a4d6616bd04f87335b0e53351227a9ee
+
+COUNT = 118
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffe00
+CIPHERTEXT = 7f692b03945867d16179a8cefc83ea3f
+
+COUNT = 119
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffff00
+CIPHERTEXT = 3bd141ee84a0e6414a26e7a4f281f8a2
+
+COUNT = 120
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffff80
+CIPHERTEXT = d1788f572d98b2b16ec5d5f3922b99bc
+
+COUNT = 121
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffffc0
+CIPHERTEXT = 0833ff6f61d98a57b288e8c3586b85a6
+
+COUNT = 122
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffffe0
+CIPHERTEXT = 8568261797de176bf0b43becc6285afb
+
+COUNT = 123
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffff0
+CIPHERTEXT = f9b0fda0c4a898f5b9e6f661c4ce4d07
+
+COUNT = 124
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffff8
+CIPHERTEXT = 8ade895913685c67c5269f8aae42983e
+
+COUNT = 125
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffffc
+CIPHERTEXT = 39bde67d5c8ed8a8b1c37eb8fa9f5ac0
+
+COUNT = 126
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffffe
+CIPHERTEXT = 5c005e72c1418c44f569f2ea33ba54f3
+
+COUNT = 127
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffffff
+CIPHERTEXT = 3f5b8cc9ea855a0afa7347d23e8d664e
+
+
+ECB Varying Key 128 bits
+
+COUNT = 0
+KEY = 80000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 0edd33d3c621e546455bd8ba1418bec8
+
+COUNT = 1
+KEY = c0000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4bc3f883450c113c64ca42e1112a9e87
+
+COUNT = 2
+KEY = e0000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 72a1da770f5d7ac4c9ef94d822affd97
+
+COUNT = 3
+KEY = f0000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 970014d634e2b7650777e8e84d03ccd8
+
+COUNT = 4
+KEY = f8000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f17e79aed0db7e279e955b5f493875a7
+
+COUNT = 5
+KEY = fc000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9ed5a75136a940d0963da379db4af26a
+
+COUNT = 6
+KEY = fe000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c4295f83465c7755e8fa364bac6a7ea5
+
+COUNT = 7
+KEY = ff000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b1d758256b28fd850ad4944208cf1155
+
+COUNT = 8
+KEY = ff800000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 42ffb34c743de4d88ca38011c990890b
+
+COUNT = 9
+KEY = ffc00000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9958f0ecea8b2172c0c1995f9182c0f3
+
+COUNT = 10
+KEY = ffe00000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 956d7798fac20f82a8823f984d06f7f5
+
+COUNT = 11
+KEY = fff00000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a01bf44f2d16be928ca44aaf7b9b106b
+
+COUNT = 12
+KEY = fff80000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b5f1a33e50d40d103764c76bd4c6b6f8
+
+COUNT = 13
+KEY = fffc0000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2637050c9fc0d4817e2d69de878aee8d
+
+COUNT = 14
+KEY = fffe0000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 113ecbe4a453269a0dd26069467fb5b5
+
+COUNT = 15
+KEY = ffff0000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 97d0754fe68f11b9e375d070a608c884
+
+COUNT = 16
+KEY = ffff8000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c6a0b3e998d05068a5399778405200b4
+
+COUNT = 17
+KEY = ffffc000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = df556a33438db87bc41b1752c55e5e49
+
+COUNT = 18
+KEY = ffffe000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 90fb128d3a1af6e548521bb962bf1f05
+
+COUNT = 19
+KEY = fffff000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 26298e9c1db517c215fadfb7d2a8d691
+
+COUNT = 20
+KEY = fffff800000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a6cb761d61f8292d0df393a279ad0380
+
+COUNT = 21
+KEY = fffffc00000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 12acd89b13cd5f8726e34d44fd486108
+
+COUNT = 22
+KEY = fffffe00000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 95b1703fc57ba09fe0c3580febdd7ed4
+
+COUNT = 23
+KEY = ffffff00000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = de11722d893e9f9121c381becc1da59a
+
+COUNT = 24
+KEY = ffffff80000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6d114ccb27bf391012e8974c546d9bf2
+
+COUNT = 25
+KEY = ffffffc0000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5ce37e17eb4646ecfac29b9cc38d9340
+
+COUNT = 26
+KEY = ffffffe0000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 18c1b6e2157122056d0243d8a165cddb
+
+COUNT = 27
+KEY = fffffff0000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 99693e6a59d1366c74d823562d7e1431
+
+COUNT = 28
+KEY = fffffff8000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6c7c64dc84a8bba758ed17eb025a57e3
+
+COUNT = 29
+KEY = fffffffc000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e17bc79f30eaab2fac2cbbe3458d687a
+
+COUNT = 30
+KEY = fffffffe000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1114bc2028009b923f0b01915ce5e7c4
+
+COUNT = 31
+KEY = ffffffff000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9c28524a16a1e1c1452971caa8d13476
+
+COUNT = 32
+KEY = ffffffff800000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ed62e16363638360fdd6ad62112794f0
+
+COUNT = 33
+KEY = ffffffffc00000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5a8688f0b2a2c16224c161658ffd4044
+
+COUNT = 34
+KEY = ffffffffe00000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 23f710842b9bb9c32f26648c786807ca
+
+COUNT = 35
+KEY = fffffffff00000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 44a98bf11e163f632c47ec6a49683a89
+
+COUNT = 36
+KEY = fffffffff80000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 0f18aff94274696d9b61848bd50ac5e5
+
+COUNT = 37
+KEY = fffffffffc0000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 82408571c3e2424540207f833b6dda69
+
+COUNT = 38
+KEY = fffffffffe0000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 303ff996947f0c7d1f43c8f3027b9b75
+
+COUNT = 39
+KEY = ffffffffff0000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7df4daf4ad29a3615a9b6ece5c99518a
+
+COUNT = 40
+KEY = ffffffffff8000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c72954a48d0774db0b4971c526260415
+
+COUNT = 41
+KEY = ffffffffffc000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1df9b76112dc6531e07d2cfda04411f0
+
+COUNT = 42
+KEY = ffffffffffe000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8e4d8e699119e1fc87545a647fb1d34f
+
+COUNT = 43
+KEY = fffffffffff000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e6c4807ae11f36f091c57d9fb68548d1
+
+COUNT = 44
+KEY = fffffffffff800000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8ebf73aad49c82007f77a5c1ccec6ab4
+
+COUNT = 45
+KEY = fffffffffffc00000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4fb288cc2040049001d2c7585ad123fc
+
+COUNT = 46
+KEY = fffffffffffe00000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 04497110efb9dceb13e2b13fb4465564
+
+COUNT = 47
+KEY = ffffffffffff00000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 75550e6cb5a88e49634c9ab69eda0430
+
+COUNT = 48
+KEY = ffffffffffff80000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b6768473ce9843ea66a81405dd50b345
+
+COUNT = 49
+KEY = ffffffffffffc0000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cb2f430383f9084e03a653571e065de6
+
+COUNT = 50
+KEY = ffffffffffffe0000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ff4e66c07bae3e79fb7d210847a3b0ba
+
+COUNT = 51
+KEY = fffffffffffff0000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7b90785125505fad59b13c186dd66ce3
+
+COUNT = 52
+KEY = fffffffffffff8000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8b527a6aebdaec9eaef8eda2cb7783e5
+
+COUNT = 53
+KEY = fffffffffffffc000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 43fdaf53ebbc9880c228617d6a9b548b
+
+COUNT = 54
+KEY = fffffffffffffe000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 53786104b9744b98f052c46f1c850d0b
+
+COUNT = 55
+KEY = ffffffffffffff000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b5ab3013dd1e61df06cbaf34ca2aee78
+
+COUNT = 56
+KEY = ffffffffffffff800000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7470469be9723030fdcc73a8cd4fbb10
+
+COUNT = 57
+KEY = ffffffffffffffc00000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a35a63f5343ebe9ef8167bcb48ad122e
+
+COUNT = 58
+KEY = ffffffffffffffe00000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fd8687f0757a210e9fdf181204c30863
+
+COUNT = 59
+KEY = fffffffffffffff00000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7a181e84bd5457d26a88fbae96018fb0
+
+COUNT = 60
+KEY = fffffffffffffff80000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 653317b9362b6f9b9e1a580e68d494b5
+
+COUNT = 61
+KEY = fffffffffffffffc0000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 995c9dc0b689f03c45867b5faa5c18d1
+
+COUNT = 62
+KEY = fffffffffffffffe0000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 77a4d96d56dda398b9aabecfc75729fd
+
+COUNT = 63
+KEY = ffffffffffffffff0000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 84be19e053635f09f2665e7bae85b42d
+
+COUNT = 64
+KEY = ffffffffffffffff8000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 32cd652842926aea4aa6137bb2be2b5e
+
+COUNT = 65
+KEY = ffffffffffffffffc000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 493d4a4f38ebb337d10aa84e9171a554
+
+COUNT = 66
+KEY = ffffffffffffffffe000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d9bff7ff454b0ec5a4a2a69566e2cb84
+
+COUNT = 67
+KEY = fffffffffffffffff000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3535d565ace3f31eb249ba2cc6765d7a
+
+COUNT = 68
+KEY = fffffffffffffffff800000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f60e91fc3269eecf3231c6e9945697c6
+
+COUNT = 69
+KEY = fffffffffffffffffc00000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ab69cfadf51f8e604d9cc37182f6635a
+
+COUNT = 70
+KEY = fffffffffffffffffe00000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7866373f24a0b6ed56e0d96fcdafb877
+
+COUNT = 71
+KEY = ffffffffffffffffff00000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1ea448c2aac954f5d812e9d78494446a
+
+COUNT = 72
+KEY = ffffffffffffffffff80000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = acc5599dd8ac02239a0fef4a36dd1668
+
+COUNT = 73
+KEY = ffffffffffffffffffc0000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d8764468bb103828cf7e1473ce895073
+
+COUNT = 74
+KEY = ffffffffffffffffffe0000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1b0d02893683b9f180458e4aa6b73982
+
+COUNT = 75
+KEY = fffffffffffffffffff0000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 96d9b017d302df410a937dcdb8bb6e43
+
+COUNT = 76
+KEY = fffffffffffffffffff8000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ef1623cc44313cff440b1594a7e21cc6
+
+COUNT = 77
+KEY = fffffffffffffffffffc000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 284ca2fa35807b8b0ae4d19e11d7dbd7
+
+COUNT = 78
+KEY = fffffffffffffffffffe000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f2e976875755f9401d54f36e2a23a594
+
+COUNT = 79
+KEY = ffffffffffffffffffff000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ec198a18e10e532403b7e20887c8dd80
+
+COUNT = 80
+KEY = ffffffffffffffffffff800000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 545d50ebd919e4a6949d96ad47e46a80
+
+COUNT = 81
+KEY = ffffffffffffffffffffc00000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = dbdfb527060e0a71009c7bb0c68f1d44
+
+COUNT = 82
+KEY = ffffffffffffffffffffe00000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9cfa1322ea33da2173a024f2ff0d896d
+
+COUNT = 83
+KEY = fffffffffffffffffffff00000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8785b1a75b0f3bd958dcd0e29318c521
+
+COUNT = 84
+KEY = fffffffffffffffffffff80000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 38f67b9e98e4a97b6df030a9fcdd0104
+
+COUNT = 85
+KEY = fffffffffffffffffffffc0000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 192afffb2c880e82b05926d0fc6c448b
+
+COUNT = 86
+KEY = fffffffffffffffffffffe0000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6a7980ce7b105cf530952d74daaf798c
+
+COUNT = 87
+KEY = ffffffffffffffffffffff0000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ea3695e1351b9d6858bd958cf513ef6c
+
+COUNT = 88
+KEY = ffffffffffffffffffffff8000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6da0490ba0ba0343b935681d2cce5ba1
+
+COUNT = 89
+KEY = ffffffffffffffffffffffc000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f0ea23af08534011c60009ab29ada2f1
+
+COUNT = 90
+KEY = ffffffffffffffffffffffe000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ff13806cf19cc38721554d7c0fcdcd4b
+
+COUNT = 91
+KEY = fffffffffffffffffffffff000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6838af1f4f69bae9d85dd188dcdf0688
+
+COUNT = 92
+KEY = fffffffffffffffffffffff800000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 36cf44c92d550bfb1ed28ef583ddf5d7
+
+COUNT = 93
+KEY = fffffffffffffffffffffffc00000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d06e3195b5376f109d5c4ec6c5d62ced
+
+COUNT = 94
+KEY = fffffffffffffffffffffffe00000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c440de014d3d610707279b13242a5c36
+
+COUNT = 95
+KEY = ffffffffffffffffffffffff00000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f0c5c6ffa5e0bd3a94c88f6b6f7c16b9
+
+COUNT = 96
+KEY = ffffffffffffffffffffffff80000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3e40c3901cd7effc22bffc35dee0b4d9
+
+COUNT = 97
+KEY = ffffffffffffffffffffffffc0000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b63305c72bedfab97382c406d0c49bc6
+
+COUNT = 98
+KEY = ffffffffffffffffffffffffe0000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 36bbaab22a6bd4925a99a2b408d2dbae
+
+COUNT = 99
+KEY = fffffffffffffffffffffffff0000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 307c5b8fcd0533ab98bc51e27a6ce461
+
+COUNT = 100
+KEY = fffffffffffffffffffffffff8000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 829c04ff4c07513c0b3ef05c03e337b5
+
+COUNT = 101
+KEY = fffffffffffffffffffffffffc000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f17af0e895dda5eb98efc68066e84c54
+
+COUNT = 102
+KEY = fffffffffffffffffffffffffe000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 277167f3812afff1ffacb4a934379fc3
+
+COUNT = 103
+KEY = ffffffffffffffffffffffffff000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2cb1dc3a9c72972e425ae2ef3eb597cd
+
+COUNT = 104
+KEY = ffffffffffffffffffffffffff800000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 36aeaa3a213e968d4b5b679d3a2c97fe
+
+COUNT = 105
+KEY = ffffffffffffffffffffffffffc00000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9241daca4fdd034a82372db50e1a0f3f
+
+COUNT = 106
+KEY = ffffffffffffffffffffffffffe00000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c14574d9cd00cf2b5a7f77e53cd57885
+
+COUNT = 107
+KEY = fffffffffffffffffffffffffff00000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 793de39236570aba83ab9b737cb521c9
+
+COUNT = 108
+KEY = fffffffffffffffffffffffffff80000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 16591c0f27d60e29b85a96c33861a7ef
+
+COUNT = 109
+KEY = fffffffffffffffffffffffffffc0000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 44fb5c4d4f5cb79be5c174a3b1c97348
+
+COUNT = 110
+KEY = fffffffffffffffffffffffffffe0000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 674d2b61633d162be59dde04222f4740
+
+COUNT = 111
+KEY = ffffffffffffffffffffffffffff0000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b4750ff263a65e1f9e924ccfd98f3e37
+
+COUNT = 112
+KEY = ffffffffffffffffffffffffffff8000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 62d0662d6eaeddedebae7f7ea3a4f6b6
+
+COUNT = 113
+KEY = ffffffffffffffffffffffffffffc000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 70c46bb30692be657f7eaa93ebad9897
+
+COUNT = 114
+KEY = ffffffffffffffffffffffffffffe000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 323994cfb9da285a5d9642e1759b224a
+
+COUNT = 115
+KEY = fffffffffffffffffffffffffffff000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1dbf57877b7b17385c85d0b54851e371
+
+COUNT = 116
+KEY = fffffffffffffffffffffffffffff800
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = dfa5c097cdc1532ac071d57b1d28d1bd
+
+COUNT = 117
+KEY = fffffffffffffffffffffffffffffc00
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3a0c53fa37311fc10bd2a9981f513174
+
+COUNT = 118
+KEY = fffffffffffffffffffffffffffffe00
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ba4f970c0a25c41814bdae2e506be3b4
+
+COUNT = 119
+KEY = ffffffffffffffffffffffffffffff00
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2dce3acb727cd13ccd76d425ea56e4f6
+
+COUNT = 120
+KEY = ffffffffffffffffffffffffffffff80
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5160474d504b9b3eefb68d35f245f4b3
+
+COUNT = 121
+KEY = ffffffffffffffffffffffffffffffc0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 41a8a947766635dec37553d9a6c0cbb7
+
+COUNT = 122
+KEY = ffffffffffffffffffffffffffffffe0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 25d6cfe6881f2bf497dd14cd4ddf445b
+
+COUNT = 123
+KEY = fffffffffffffffffffffffffffffff0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 41c78c135ed9e98c096640647265da1e
+
+COUNT = 124
+KEY = fffffffffffffffffffffffffffffff8
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5a4d404d8917e353e92a21072c3b2305
+
+COUNT = 125
+KEY = fffffffffffffffffffffffffffffffc
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 02bc96846b3fdc71643f384cd3cc3eaf
+
+COUNT = 126
+KEY = fffffffffffffffffffffffffffffffe
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9ba4a9143f4e5d4048521c4f8877d88e
+
+COUNT = 127
+KEY = ffffffffffffffffffffffffffffffff
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a1f6258c877d5fcd8964484538bfc92c
+
+
+ECB Varying Plaintext 192 bits
+
+COUNT = 0
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = 80000000000000000000000000000000
+CIPHERTEXT = 6cd02513e8d4dc986b4afe087a60bd0c
+
+COUNT = 1
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = c0000000000000000000000000000000
+CIPHERTEXT = 2ce1f8b7e30627c1c4519eada44bc436
+
+COUNT = 2
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = e0000000000000000000000000000000
+CIPHERTEXT = 9946b5f87af446f5796c1fee63a2da24
+
+COUNT = 3
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = f0000000000000000000000000000000
+CIPHERTEXT = 2a560364ce529efc21788779568d5555
+
+COUNT = 4
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = f8000000000000000000000000000000
+CIPHERTEXT = 35c1471837af446153bce55d5ba72a0a
+
+COUNT = 5
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fc000000000000000000000000000000
+CIPHERTEXT = ce60bc52386234f158f84341e534cd9e
+
+COUNT = 6
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fe000000000000000000000000000000
+CIPHERTEXT = 8c7c27ff32bcf8dc2dc57c90c2903961
+
+COUNT = 7
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ff000000000000000000000000000000
+CIPHERTEXT = 32bb6a7ec84499e166f936003d55a5bb
+
+COUNT = 8
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ff800000000000000000000000000000
+CIPHERTEXT = a5c772e5c62631ef660ee1d5877f6d1b
+
+COUNT = 9
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffc00000000000000000000000000000
+CIPHERTEXT = 030d7e5b64f380a7e4ea5387b5cd7f49
+
+COUNT = 10
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffe00000000000000000000000000000
+CIPHERTEXT = 0dc9a2610037009b698f11bb7e86c83e
+
+COUNT = 11
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fff00000000000000000000000000000
+CIPHERTEXT = 0046612c766d1840c226364f1fa7ed72
+
+COUNT = 12
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fff80000000000000000000000000000
+CIPHERTEXT = 4880c7e08f27befe78590743c05e698b
+
+COUNT = 13
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffc0000000000000000000000000000
+CIPHERTEXT = 2520ce829a26577f0f4822c4ecc87401
+
+COUNT = 14
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffe0000000000000000000000000000
+CIPHERTEXT = 8765e8acc169758319cb46dc7bcf3dca
+
+COUNT = 15
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffff0000000000000000000000000000
+CIPHERTEXT = e98f4ba4f073df4baa116d011dc24a28
+
+COUNT = 16
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffff8000000000000000000000000000
+CIPHERTEXT = f378f68c5dbf59e211b3a659a7317d94
+
+COUNT = 17
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffc000000000000000000000000000
+CIPHERTEXT = 283d3b069d8eb9fb432d74b96ca762b4
+
+COUNT = 18
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffe000000000000000000000000000
+CIPHERTEXT = a7e1842e8a87861c221a500883245c51
+
+COUNT = 19
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffff000000000000000000000000000
+CIPHERTEXT = 77aa270471881be070fb52c7067ce732
+
+COUNT = 20
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffff800000000000000000000000000
+CIPHERTEXT = 01b0f476d484f43f1aeb6efa9361a8ac
+
+COUNT = 21
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffc00000000000000000000000000
+CIPHERTEXT = 1c3a94f1c052c55c2d8359aff2163b4f
+
+COUNT = 22
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffe00000000000000000000000000
+CIPHERTEXT = e8a067b604d5373d8b0f2e05a03b341b
+
+COUNT = 23
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffff00000000000000000000000000
+CIPHERTEXT = a7876ec87f5a09bfea42c77da30fd50e
+
+COUNT = 24
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffff80000000000000000000000000
+CIPHERTEXT = 0cf3e9d3a42be5b854ca65b13f35f48d
+
+COUNT = 25
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffc0000000000000000000000000
+CIPHERTEXT = 6c62f6bbcab7c3e821c9290f08892dda
+
+COUNT = 26
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffe0000000000000000000000000
+CIPHERTEXT = 7f5e05bd2068738196fee79ace7e3aec
+
+COUNT = 27
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffff0000000000000000000000000
+CIPHERTEXT = 440e0d733255cda92fb46e842fe58054
+
+COUNT = 28
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffff8000000000000000000000000
+CIPHERTEXT = aa5d5b1c4ea1b7a22e5583ac2e9ed8a7
+
+COUNT = 29
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffc000000000000000000000000
+CIPHERTEXT = 77e537e89e8491e8662aae3bc809421d
+
+COUNT = 30
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffe000000000000000000000000
+CIPHERTEXT = 997dd3e9f1598bfa73f75973f7e93b76
+
+COUNT = 31
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffff000000000000000000000000
+CIPHERTEXT = 1b38d4f7452afefcb7fc721244e4b72e
+
+COUNT = 32
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffff800000000000000000000000
+CIPHERTEXT = 0be2b18252e774dda30cdda02c6906e3
+
+COUNT = 33
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffc00000000000000000000000
+CIPHERTEXT = d2695e59c20361d82652d7d58b6f11b2
+
+COUNT = 34
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffe00000000000000000000000
+CIPHERTEXT = 902d88d13eae52089abd6143cfe394e9
+
+COUNT = 35
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffff00000000000000000000000
+CIPHERTEXT = d49bceb3b823fedd602c305345734bd2
+
+COUNT = 36
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffff80000000000000000000000
+CIPHERTEXT = 707b1dbb0ffa40ef7d95def421233fae
+
+COUNT = 37
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffc0000000000000000000000
+CIPHERTEXT = 7ca0c1d93356d9eb8aa952084d75f913
+
+COUNT = 38
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffe0000000000000000000000
+CIPHERTEXT = f2cbf9cb186e270dd7bdb0c28febc57d
+
+COUNT = 39
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffff0000000000000000000000
+CIPHERTEXT = c94337c37c4e790ab45780bd9c3674a0
+
+COUNT = 40
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffff8000000000000000000000
+CIPHERTEXT = 8e3558c135252fb9c9f367ed609467a1
+
+COUNT = 41
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffc000000000000000000000
+CIPHERTEXT = 1b72eeaee4899b443914e5b3a57fba92
+
+COUNT = 42
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffe000000000000000000000
+CIPHERTEXT = 011865f91bc56868d051e52c9efd59b7
+
+COUNT = 43
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffff000000000000000000000
+CIPHERTEXT = e4771318ad7a63dd680f6e583b7747ea
+
+COUNT = 44
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffff800000000000000000000
+CIPHERTEXT = 61e3d194088dc8d97e9e6db37457eac5
+
+COUNT = 45
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffc00000000000000000000
+CIPHERTEXT = 36ff1ec9ccfbc349e5d356d063693ad6
+
+COUNT = 46
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffe00000000000000000000
+CIPHERTEXT = 3cc9e9a9be8cc3f6fb2ea24088e9bb19
+
+COUNT = 47
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffff00000000000000000000
+CIPHERTEXT = 1ee5ab003dc8722e74905d9a8fe3d350
+
+COUNT = 48
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffff80000000000000000000
+CIPHERTEXT = 245339319584b0a412412869d6c2eada
+
+COUNT = 49
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffc0000000000000000000
+CIPHERTEXT = 7bd496918115d14ed5380852716c8814
+
+COUNT = 50
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffe0000000000000000000
+CIPHERTEXT = 273ab2f2b4a366a57d582a339313c8b1
+
+COUNT = 51
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffff0000000000000000000
+CIPHERTEXT = 113365a9ffbe3b0ca61e98507554168b
+
+COUNT = 52
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffff8000000000000000000
+CIPHERTEXT = afa99c997ac478a0dea4119c9e45f8b1
+
+COUNT = 53
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffc000000000000000000
+CIPHERTEXT = 9216309a7842430b83ffb98638011512
+
+COUNT = 54
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffe000000000000000000
+CIPHERTEXT = 62abc792288258492a7cb45145f4b759
+
+COUNT = 55
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffff000000000000000000
+CIPHERTEXT = 534923c169d504d7519c15d30e756c50
+
+COUNT = 56
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffff800000000000000000
+CIPHERTEXT = fa75e05bcdc7e00c273fa33f6ee441d2
+
+COUNT = 57
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffc00000000000000000
+CIPHERTEXT = 7d350fa6057080f1086a56b17ec240db
+
+COUNT = 58
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffe00000000000000000
+CIPHERTEXT = f34e4a6324ea4a5c39a661c8fe5ada8f
+
+COUNT = 59
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffff00000000000000000
+CIPHERTEXT = 0882a16f44088d42447a29ac090ec17e
+
+COUNT = 60
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffff80000000000000000
+CIPHERTEXT = 3a3c15bfc11a9537c130687004e136ee
+
+COUNT = 61
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffc0000000000000000
+CIPHERTEXT = 22c0a7678dc6d8cf5c8a6d5a9960767c
+
+COUNT = 62
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffe0000000000000000
+CIPHERTEXT = b46b09809d68b9a456432a79bdc2e38c
+
+COUNT = 63
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffff0000000000000000
+CIPHERTEXT = 93baaffb35fbe739c17c6ac22eecf18f
+
+COUNT = 64
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffff8000000000000000
+CIPHERTEXT = c8aa80a7850675bc007c46df06b49868
+
+COUNT = 65
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffc000000000000000
+CIPHERTEXT = 12c6f3877af421a918a84b775858021d
+
+COUNT = 66
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffe000000000000000
+CIPHERTEXT = 33f123282c5d633924f7d5ba3f3cab11
+
+COUNT = 67
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffff000000000000000
+CIPHERTEXT = a8f161002733e93ca4527d22c1a0c5bb
+
+COUNT = 68
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffff800000000000000
+CIPHERTEXT = b72f70ebf3e3fda23f508eec76b42c02
+
+COUNT = 69
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffc00000000000000
+CIPHERTEXT = 6a9d965e6274143f25afdcfc88ffd77c
+
+COUNT = 70
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffe00000000000000
+CIPHERTEXT = a0c74fd0b9361764ce91c5200b095357
+
+COUNT = 71
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffff00000000000000
+CIPHERTEXT = 091d1fdc2bd2c346cd5046a8c6209146
+
+COUNT = 72
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffff80000000000000
+CIPHERTEXT = e2a37580116cfb71856254496ab0aca8
+
+COUNT = 73
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffc0000000000000
+CIPHERTEXT = e0b3a00785917c7efc9adba322813571
+
+COUNT = 74
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffe0000000000000
+CIPHERTEXT = 733d41f4727b5ef0df4af4cf3cffa0cb
+
+COUNT = 75
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffff0000000000000
+CIPHERTEXT = a99ebb030260826f981ad3e64490aa4f
+
+COUNT = 76
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffff8000000000000
+CIPHERTEXT = 73f34c7d3eae5e80082c1647524308ee
+
+COUNT = 77
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffc000000000000
+CIPHERTEXT = 40ebd5ad082345b7a2097ccd3464da02
+
+COUNT = 78
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffe000000000000
+CIPHERTEXT = 7cc4ae9a424b2cec90c97153c2457ec5
+
+COUNT = 79
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffff000000000000
+CIPHERTEXT = 54d632d03aba0bd0f91877ebdd4d09cb
+
+COUNT = 80
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffff800000000000
+CIPHERTEXT = d3427be7e4d27cd54f5fe37b03cf0897
+
+COUNT = 81
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffc00000000000
+CIPHERTEXT = b2099795e88cc158fd75ea133d7e7fbe
+
+COUNT = 82
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffe00000000000
+CIPHERTEXT = a6cae46fb6fadfe7a2c302a34242817b
+
+COUNT = 83
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffff00000000000
+CIPHERTEXT = 026a7024d6a902e0b3ffccbaa910cc3f
+
+COUNT = 84
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffff80000000000
+CIPHERTEXT = 156f07767a85a4312321f63968338a01
+
+COUNT = 85
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffc0000000000
+CIPHERTEXT = 15eec9ebf42b9ca76897d2cd6c5a12e2
+
+COUNT = 86
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffe0000000000
+CIPHERTEXT = db0d3a6fdcc13f915e2b302ceeb70fd8
+
+COUNT = 87
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffff0000000000
+CIPHERTEXT = 71dbf37e87a2e34d15b20e8f10e48924
+
+COUNT = 88
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffff8000000000
+CIPHERTEXT = c745c451e96ff3c045e4367c833e3b54
+
+COUNT = 89
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffc000000000
+CIPHERTEXT = 340da09c2dd11c3b679d08ccd27dd595
+
+COUNT = 90
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffe000000000
+CIPHERTEXT = 8279f7c0c2a03ee660c6d392db025d18
+
+COUNT = 91
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffff000000000
+CIPHERTEXT = a4b2c7d8eba531ff47c5041a55fbd1ec
+
+COUNT = 92
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffff800000000
+CIPHERTEXT = 74569a2ca5a7bd5131ce8dc7cbfbf72f
+
+COUNT = 93
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffc00000000
+CIPHERTEXT = 3713da0c0219b63454035613b5a403dd
+
+COUNT = 94
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffe00000000
+CIPHERTEXT = 8827551ddcc9df23fa72a3de4e9f0b07
+
+COUNT = 95
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffff00000000
+CIPHERTEXT = 2e3febfd625bfcd0a2c06eb460da1732
+
+COUNT = 96
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffff80000000
+CIPHERTEXT = ee82e6ba488156f76496311da6941deb
+
+COUNT = 97
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffc0000000
+CIPHERTEXT = 4770446f01d1f391256e85a1b30d89d3
+
+COUNT = 98
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffe0000000
+CIPHERTEXT = af04b68f104f21ef2afb4767cf74143c
+
+COUNT = 99
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffff0000000
+CIPHERTEXT = cf3579a9ba38c8e43653173e14f3a4c6
+
+COUNT = 100
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffff8000000
+CIPHERTEXT = b3bba904f4953e09b54800af2f62e7d4
+
+COUNT = 101
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffc000000
+CIPHERTEXT = fc4249656e14b29eb9c44829b4c59a46
+
+COUNT = 102
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffe000000
+CIPHERTEXT = 9b31568febe81cfc2e65af1c86d1a308
+
+COUNT = 103
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffff000000
+CIPHERTEXT = 9ca09c25f273a766db98a480ce8dfedc
+
+COUNT = 104
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffff800000
+CIPHERTEXT = b909925786f34c3c92d971883c9fbedf
+
+COUNT = 105
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffc00000
+CIPHERTEXT = 82647f1332fe570a9d4d92b2ee771d3b
+
+COUNT = 106
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffe00000
+CIPHERTEXT = 3604a7e80832b3a99954bca6f5b9f501
+
+COUNT = 107
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffff00000
+CIPHERTEXT = 884607b128c5de3ab39a529a1ef51bef
+
+COUNT = 108
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffff80000
+CIPHERTEXT = 670cfa093d1dbdb2317041404102435e
+
+COUNT = 109
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffc0000
+CIPHERTEXT = 7a867195f3ce8769cbd336502fbb5130
+
+COUNT = 110
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffe0000
+CIPHERTEXT = 52efcf64c72b2f7ca5b3c836b1078c15
+
+COUNT = 111
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffff0000
+CIPHERTEXT = 4019250f6eefb2ac5ccbcae044e75c7e
+
+COUNT = 112
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffff8000
+CIPHERTEXT = 022c4f6f5a017d292785627667ddef24
+
+COUNT = 113
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffc000
+CIPHERTEXT = e9c21078a2eb7e03250f71000fa9e3ed
+
+COUNT = 114
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffe000
+CIPHERTEXT = a13eaeeb9cd391da4e2b09490b3e7fad
+
+COUNT = 115
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffff000
+CIPHERTEXT = c958a171dca1d4ed53e1af1d380803a9
+
+COUNT = 116
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffff800
+CIPHERTEXT = 21442e07a110667f2583eaeeee44dc8c
+
+COUNT = 117
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffc00
+CIPHERTEXT = 59bbb353cf1dd867a6e33737af655e99
+
+COUNT = 118
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffe00
+CIPHERTEXT = 43cd3b25375d0ce41087ff9fe2829639
+
+COUNT = 119
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffff00
+CIPHERTEXT = 6b98b17e80d1118e3516bd768b285a84
+
+COUNT = 120
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffff80
+CIPHERTEXT = ae47ed3676ca0c08deea02d95b81db58
+
+COUNT = 121
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffffc0
+CIPHERTEXT = 34ec40dc20413795ed53628ea748720b
+
+COUNT = 122
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffffe0
+CIPHERTEXT = 4dc68163f8e9835473253542c8a65d46
+
+COUNT = 123
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffff0
+CIPHERTEXT = 2aabb999f43693175af65c6c612c46fb
+
+COUNT = 124
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffff8
+CIPHERTEXT = e01f94499dac3547515c5b1d756f0f58
+
+COUNT = 125
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffffc
+CIPHERTEXT = 9d12435a46480ce00ea349f71799df9a
+
+COUNT = 126
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffffe
+CIPHERTEXT = cef41d16d266bdfe46938ad7884cc0cf
+
+COUNT = 127
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffffff
+CIPHERTEXT = b13db4da1f718bc6904797c82bcf2d32
+
+
+ECB Varying Key 192 bits
+
+COUNT = 0
+KEY = 800000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = de885dc87f5a92594082d02cc1e1b42c
+
+COUNT = 1
+KEY = c00000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 132b074e80f2a597bf5febd8ea5da55e
+
+COUNT = 2
+KEY = e00000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6eccedf8de592c22fb81347b79f2db1f
+
+COUNT = 3
+KEY = f00000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 180b09f267c45145db2f826c2582d35c
+
+COUNT = 4
+KEY = f80000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = edd807ef7652d7eb0e13c8b5e15b3bc0
+
+COUNT = 5
+KEY = fc0000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9978bcf8dd8fd72241223ad24b31b8a4
+
+COUNT = 6
+KEY = fe0000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5310f654343e8f27e12c83a48d24ff81
+
+COUNT = 7
+KEY = ff0000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 833f71258d53036b02952c76c744f5a1
+
+COUNT = 8
+KEY = ff8000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = eba83ff200cff9318a92f8691a06b09f
+
+COUNT = 9
+KEY = ffc000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ff620ccbe9f3292abdf2176b09f04eba
+
+COUNT = 10
+KEY = ffe000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7ababc4b3f516c9aafb35f4140b548f9
+
+COUNT = 11
+KEY = fff000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = aa187824d9c4582b0916493ecbde8c57
+
+COUNT = 12
+KEY = fff800000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1c0ad553177fd5ea1092c9d626a29dc4
+
+COUNT = 13
+KEY = fffc00000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a5dc46c37261194124ecaebd680408ec
+
+COUNT = 14
+KEY = fffe00000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e4f2f2ae23e9b10bacfa58601531ba54
+
+COUNT = 15
+KEY = ffff00000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b7d67cf1a1e91e8ff3a57a172c7bf412
+
+COUNT = 16
+KEY = ffff80000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 26706be06967884e847d137128ce47b3
+
+COUNT = 17
+KEY = ffffc0000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b2f8b409b0585909aad3a7b5a219072a
+
+COUNT = 18
+KEY = ffffe0000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5e4b7bff0290c78344c54a23b722cd20
+
+COUNT = 19
+KEY = fffff0000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 07093657552d4414227ce161e9ebf7dd
+
+COUNT = 20
+KEY = fffff8000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e1af1e7d8bc225ed4dffb771ecbb9e67
+
+COUNT = 21
+KEY = fffffc000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ef6555253635d8432156cfd9c11b145a
+
+COUNT = 22
+KEY = fffffe000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fb4035074a5d4260c90cbd6da6c3fceb
+
+COUNT = 23
+KEY = ffffff000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 446ee416f9ad1c103eb0cc96751c88e1
+
+COUNT = 24
+KEY = ffffff800000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 198ae2a4637ac0a7890a8fd1485445c9
+
+COUNT = 25
+KEY = ffffffc00000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 562012ec8faded0825fb2fa70ab30cbd
+
+COUNT = 26
+KEY = ffffffe00000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cc8a64b46b5d88bf7f247d4dbaf38f05
+
+COUNT = 27
+KEY = fffffff00000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a168253762e2cc81b42d1e5001762699
+
+COUNT = 28
+KEY = fffffff80000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1b41f83b38ce5032c6cd7af98cf62061
+
+COUNT = 29
+KEY = fffffffc0000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 61a89990cd1411750d5fb0dc988447d4
+
+COUNT = 30
+KEY = fffffffe0000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b5accc8ed629edf8c68a539183b1ea82
+
+COUNT = 31
+KEY = ffffffff0000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b16fa71f846b81a13f361c43a851f290
+
+COUNT = 32
+KEY = ffffffff8000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4fad6efdff5975aee7692234bcd54488
+
+COUNT = 33
+KEY = ffffffffc000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ebfdb05a783d03082dfe5fdd80a00b17
+
+COUNT = 34
+KEY = ffffffffe000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = eb81b584766997af6ba5529d3bdd8609
+
+COUNT = 35
+KEY = fffffffff000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 0cf4ff4f49c8a0ca060c443499e29313
+
+COUNT = 36
+KEY = fffffffff800000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cc4ba8a8e029f8b26d8afff9df133bb6
+
+COUNT = 37
+KEY = fffffffffc00000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fefebf64360f38e4e63558f0ffc550c3
+
+COUNT = 38
+KEY = fffffffffe00000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 12ad98cbf725137d6a8108c2bed99322
+
+COUNT = 39
+KEY = ffffffffff00000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6afaa996226198b3e2610413ce1b3f78
+
+COUNT = 40
+KEY = ffffffffff80000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2a8ce6747a7e39367828e290848502d9
+
+COUNT = 41
+KEY = ffffffffffc0000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 223736e8b8f89ca1e37b6deab40facf1
+
+COUNT = 42
+KEY = ffffffffffe0000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c0f797e50418b95fa6013333917a9480
+
+COUNT = 43
+KEY = fffffffffff0000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a758de37c2ece2a02c73c01fedc9a132
+
+COUNT = 44
+KEY = fffffffffff8000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3a9b87ae77bae706803966c66c73adbd
+
+COUNT = 45
+KEY = fffffffffffc000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d365ab8df8ffd782e358121a4a4fc541
+
+COUNT = 46
+KEY = fffffffffffe000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c8dcd9e6f75e6c36c8daee0466f0ed74
+
+COUNT = 47
+KEY = ffffffffffff000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c79a637beb1c0304f14014c037e736dd
+
+COUNT = 48
+KEY = ffffffffffff800000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 105f0a25e84ac930d996281a5f954dd9
+
+COUNT = 49
+KEY = ffffffffffffc00000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 42e4074b2927973e8d17ffa92f7fe615
+
+COUNT = 50
+KEY = ffffffffffffe00000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4fe2a9d2c1824449c69e3e0398f12963
+
+COUNT = 51
+KEY = fffffffffffff00000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b7f29c1e1f62847a15253b28a1e9d712
+
+COUNT = 52
+KEY = fffffffffffff80000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 36ed5d29b903f31e8983ef8b0a2bf990
+
+COUNT = 53
+KEY = fffffffffffffc0000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 27b8070270810f9d023f9dd7ff3b4aa2
+
+COUNT = 54
+KEY = fffffffffffffe0000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 94d46e155c1228f61d1a0db4815ecc4b
+
+COUNT = 55
+KEY = ffffffffffffff0000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ca6108d1d98071428eeceef1714b96dd
+
+COUNT = 56
+KEY = ffffffffffffff8000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = dc5b25b71b6296cf73dd2cdcac2f70b1
+
+COUNT = 57
+KEY = ffffffffffffffc000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 44aba95e8a06a2d9d3530d2677878c80
+
+COUNT = 58
+KEY = ffffffffffffffe000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a570d20e89b467e8f5176061b81dd396
+
+COUNT = 59
+KEY = fffffffffffffff000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 758f4467a5d8f1e7307dc30b34e404f4
+
+COUNT = 60
+KEY = fffffffffffffff800000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bcea28e9071b5a2302970ff352451bc5
+
+COUNT = 61
+KEY = fffffffffffffffc00000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7523c00bc177d331ad312e09c9015c1c
+
+COUNT = 62
+KEY = fffffffffffffffe00000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ccac61e3183747b3f5836da21a1bc4f4
+
+COUNT = 63
+KEY = ffffffffffffffff00000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 707b075791878880b44189d3522b8c30
+
+COUNT = 64
+KEY = ffffffffffffffff80000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7132d0c0e4a07593cf12ebb12be7688c
+
+COUNT = 65
+KEY = ffffffffffffffffc0000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = effbac1644deb0c784275fe56e19ead3
+
+COUNT = 66
+KEY = ffffffffffffffffe0000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a005063f30f4228b374e2459738f26bb
+
+COUNT = 67
+KEY = fffffffffffffffff0000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 29975b5f48bb68fcbbc7cea93b452ed7
+
+COUNT = 68
+KEY = fffffffffffffffff8000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cf3f2576e2afedc74bb1ca7eeec1c0e7
+
+COUNT = 69
+KEY = fffffffffffffffffc000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 07c403f5f966e0e3d9f296d6226dca28
+
+COUNT = 70
+KEY = fffffffffffffffffe000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c8c20908249ab4a34d6dd0a31327ff1a
+
+COUNT = 71
+KEY = ffffffffffffffffff000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c0541329ecb6159ab23b7fc5e6a21bca
+
+COUNT = 72
+KEY = ffffffffffffffffff800000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7aa1acf1a2ed9ba72bc6deb31d88b863
+
+COUNT = 73
+KEY = ffffffffffffffffffc00000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 808bd8eddabb6f3bf0d5a8a27be1fe8a
+
+COUNT = 74
+KEY = ffffffffffffffffffe00000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 273c7d7685e14ec66bbb96b8f05b6ddd
+
+COUNT = 75
+KEY = fffffffffffffffffff00000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 32752eefc8c2a93f91b6e73eb07cca6e
+
+COUNT = 76
+KEY = fffffffffffffffffff80000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d893e7d62f6ce502c64f75e281f9c000
+
+COUNT = 77
+KEY = fffffffffffffffffffc0000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8dfd999be5d0cfa35732c0ddc88ff5a5
+
+COUNT = 78
+KEY = fffffffffffffffffffe0000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 02647c76a300c3173b841487eb2bae9f
+
+COUNT = 79
+KEY = ffffffffffffffffffff0000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 172df8b02f04b53adab028b4e01acd87
+
+COUNT = 80
+KEY = ffffffffffffffffffff8000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 054b3bf4998aeb05afd87ec536533a36
+
+COUNT = 81
+KEY = ffffffffffffffffffffc000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3783f7bf44c97f065258a666cae03020
+
+COUNT = 82
+KEY = ffffffffffffffffffffe000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = aad4c8a63f80954104de7b92cede1be1
+
+COUNT = 83
+KEY = fffffffffffffffffffff000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cbfe61810fd5467ccdacb75800f3ac07
+
+COUNT = 84
+KEY = fffffffffffffffffffff800000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 830d8a2590f7d8e1b55a737f4af45f34
+
+COUNT = 85
+KEY = fffffffffffffffffffffc00000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fffcd4683f858058e74314671d43fa2c
+
+COUNT = 86
+KEY = fffffffffffffffffffffe00000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 523d0babbb82f46ebc9e70b1cd41ddd0
+
+COUNT = 87
+KEY = ffffffffffffffffffffff00000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 344aab37080d7486f7d542a309e53eed
+
+COUNT = 88
+KEY = ffffffffffffffffffffff80000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 56c5609d0906b23ab9caca816f5dbebd
+
+COUNT = 89
+KEY = ffffffffffffffffffffffc0000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7026026eedd91adc6d831cdf9894bdc6
+
+COUNT = 90
+KEY = ffffffffffffffffffffffe0000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 88330baa4f2b618fc9d9b021bf503d5a
+
+COUNT = 91
+KEY = fffffffffffffffffffffff0000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fc9e0ea22480b0bac935c8a8ebefcdcf
+
+COUNT = 92
+KEY = fffffffffffffffffffffff8000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 29ca779f398fb04f867da7e8a44756cb
+
+COUNT = 93
+KEY = fffffffffffffffffffffffc000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 51f89c42985786bfc43c6df8ada36832
+
+COUNT = 94
+KEY = fffffffffffffffffffffffe000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6ac1de5fb8f21d874e91c53b560c50e3
+
+COUNT = 95
+KEY = ffffffffffffffffffffffff000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 03aa9058490eda306001a8a9f48d0ca7
+
+COUNT = 96
+KEY = ffffffffffffffffffffffff800000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e34ec71d6128d4871865d617c30b37e3
+
+COUNT = 97
+KEY = ffffffffffffffffffffffffc00000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 14be1c535b17cabd0c4d93529d69bf47
+
+COUNT = 98
+KEY = ffffffffffffffffffffffffe00000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c9ef67756507beec9dd3862883478044
+
+COUNT = 99
+KEY = fffffffffffffffffffffffff00000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 40e231fa5a5948ce2134e92fc0664d4b
+
+COUNT = 100
+KEY = fffffffffffffffffffffffff80000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 03194b8e5dda5530d0c678c0b48f5d92
+
+COUNT = 101
+KEY = fffffffffffffffffffffffffc0000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 90bd086f237cc4fd99f4d76bde6b4826
+
+COUNT = 102
+KEY = fffffffffffffffffffffffffe0000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 19259761ca17130d6ed86d57cd7951ee
+
+COUNT = 103
+KEY = ffffffffffffffffffffffffff0000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d7cbb3f34b9b450f24b0e8518e54da6d
+
+COUNT = 104
+KEY = ffffffffffffffffffffffffff8000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 725b9caebe9f7f417f4068d0d2ee20b3
+
+COUNT = 105
+KEY = ffffffffffffffffffffffffffc000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9d924b934a90ce1fd39b8a9794f82672
+
+COUNT = 106
+KEY = ffffffffffffffffffffffffffe000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c50562bf094526a91c5bc63c0c224995
+
+COUNT = 107
+KEY = fffffffffffffffffffffffffff000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d2f11805046743bd74f57188d9188df7
+
+COUNT = 108
+KEY = fffffffffffffffffffffffffff800000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8dd274bd0f1b58ae345d9e7233f9b8f3
+
+COUNT = 109
+KEY = fffffffffffffffffffffffffffc00000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9d6bdc8f4ce5feb0f3bed2e4b9a9bb0b
+
+COUNT = 110
+KEY = fffffffffffffffffffffffffffe00000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fd5548bcf3f42565f7efa94562528d46
+
+COUNT = 111
+KEY = ffffffffffffffffffffffffffff00000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d2ccaebd3a4c3e80b063748131ba4a71
+
+COUNT = 112
+KEY = ffffffffffffffffffffffffffff80000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e03cb23d9e11c9d93f117e9c0a91b576
+
+COUNT = 113
+KEY = ffffffffffffffffffffffffffffc0000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 78f933a2081ac1db84f69d10f4523fe0
+
+COUNT = 114
+KEY = ffffffffffffffffffffffffffffe0000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4061f7412ed320de0edc8851c2e2436f
+
+COUNT = 115
+KEY = fffffffffffffffffffffffffffff0000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9064ba1cd04ce6bab98474330814b4d4
+
+COUNT = 116
+KEY = fffffffffffffffffffffffffffff8000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 48391bffb9cfff80ac238c886ef0a461
+
+COUNT = 117
+KEY = fffffffffffffffffffffffffffffc000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b8d2a67df5a999fdbf93edd0343296c9
+
+COUNT = 118
+KEY = fffffffffffffffffffffffffffffe000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = aaca7367396b69a221bd632bea386eec
+
+COUNT = 119
+KEY = ffffffffffffffffffffffffffffff000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a80fd5020dfe65f5f16293ec92c6fd89
+
+COUNT = 120
+KEY = ffffffffffffffffffffffffffffff800000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2162995b8217a67f1abc342e146406f8
+
+COUNT = 121
+KEY = ffffffffffffffffffffffffffffffc00000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c6a6164b7a60bae4e986ffac28dfadd9
+
+COUNT = 122
+KEY = ffffffffffffffffffffffffffffffe00000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 64e0d7f900e3d9c83e4b8f96717b2146
+
+COUNT = 123
+KEY = fffffffffffffffffffffffffffffff00000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1ad2561de8c1232f5d8dbab4739b6cbb
+
+COUNT = 124
+KEY = fffffffffffffffffffffffffffffff80000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 279689e9a557f58b1c3bf40c97a90964
+
+COUNT = 125
+KEY = fffffffffffffffffffffffffffffffc0000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c4637e4a5e6377f9cc5a8638045de029
+
+COUNT = 126
+KEY = fffffffffffffffffffffffffffffffe0000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 492e607e5aea4688594b45f3aee3df90
+
+COUNT = 127
+KEY = ffffffffffffffffffffffffffffffff0000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e8c4e4381feec74054954c05b777a00a
+
+COUNT = 128
+KEY = ffffffffffffffffffffffffffffffff8000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 91549514605f38246c9b724ad839f01d
+
+COUNT = 129
+KEY = ffffffffffffffffffffffffffffffffc000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 74b24e3b6fefe40a4f9ef7ac6e44d76a
+
+COUNT = 130
+KEY = ffffffffffffffffffffffffffffffffe000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2437a683dc5d4b52abb4a123a8df86c6
+
+COUNT = 131
+KEY = fffffffffffffffffffffffffffffffff000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bb2852c891c5947d2ed44032c421b85f
+
+COUNT = 132
+KEY = fffffffffffffffffffffffffffffffff800000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1b9f5fbd5e8a4264c0a85b80409afa5e
+
+COUNT = 133
+KEY = fffffffffffffffffffffffffffffffffc00000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 30dab809f85a917fe924733f424ac589
+
+COUNT = 134
+KEY = fffffffffffffffffffffffffffffffffe00000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = eaef5c1f8d605192646695ceadc65f32
+
+COUNT = 135
+KEY = ffffffffffffffffffffffffffffffffff00000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b8aa90040b4c15a12316b78e0f9586fc
+
+COUNT = 136
+KEY = ffffffffffffffffffffffffffffffffff80000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 97fac8297ceaabc87d454350601e0673
+
+COUNT = 137
+KEY = ffffffffffffffffffffffffffffffffffc0000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9b47ef567ac28dfe488492f157e2b2e0
+
+COUNT = 138
+KEY = ffffffffffffffffffffffffffffffffffe0000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1b8426027ddb962b5c5ba7eb8bc9ab63
+
+COUNT = 139
+KEY = fffffffffffffffffffffffffffffffffff0000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e917fc77e71992a12dbe4c18068bec82
+
+COUNT = 140
+KEY = fffffffffffffffffffffffffffffffffff8000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = dceebbc98840f8ae6daf76573b7e56f4
+
+COUNT = 141
+KEY = fffffffffffffffffffffffffffffffffffc000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4e11a9f74205125b61e0aee047eca20d
+
+COUNT = 142
+KEY = fffffffffffffffffffffffffffffffffffe000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f60467f55a1f17eab88e800120cbc284
+
+COUNT = 143
+KEY = ffffffffffffffffffffffffffffffffffff000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d436649f600b449ee276530f0cd83c11
+
+COUNT = 144
+KEY = ffffffffffffffffffffffffffffffffffff800000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3bc0e3656a9e3ac7cd378a737f53b637
+
+COUNT = 145
+KEY = ffffffffffffffffffffffffffffffffffffc00000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6bacae63d33b928aa8380f8d54d88c17
+
+COUNT = 146
+KEY = ffffffffffffffffffffffffffffffffffffe00000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8935ffbc75ae6251bf8e859f085adcb9
+
+COUNT = 147
+KEY = fffffffffffffffffffffffffffffffffffff00000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 93dc4970fe35f67747cb0562c06d875a
+
+COUNT = 148
+KEY = fffffffffffffffffffffffffffffffffffff80000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 14f9df858975851797ba604fb0d16cc7
+
+COUNT = 149
+KEY = fffffffffffffffffffffffffffffffffffffc0000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 02ea0c98dca10b38c21b3b14e8d1b71f
+
+COUNT = 150
+KEY = fffffffffffffffffffffffffffffffffffffe0000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8f091b1b5b0749b2adc803e63dda9b72
+
+COUNT = 151
+KEY = ffffffffffffffffffffffffffffffffffffff0000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 05b389e3322c6da08384345a4137fd08
+
+COUNT = 152
+KEY = ffffffffffffffffffffffffffffffffffffff8000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 381308c438f35b399f10ad71b05027d8
+
+COUNT = 153
+KEY = ffffffffffffffffffffffffffffffffffffffc000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 68c230fcfa9279c3409fc423e2acbe04
+
+COUNT = 154
+KEY = ffffffffffffffffffffffffffffffffffffffe000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1c84a475acb011f3f59f4f46b76274c0
+
+COUNT = 155
+KEY = fffffffffffffffffffffffffffffffffffffff000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 45119b68cb3f8399ee60066b5611a4d7
+
+COUNT = 156
+KEY = fffffffffffffffffffffffffffffffffffffff800000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9423762f527a4060ffca312dcca22a16
+
+COUNT = 157
+KEY = fffffffffffffffffffffffffffffffffffffffc00000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f361a2745a33f056a5ac6ace2f08e344
+
+COUNT = 158
+KEY = fffffffffffffffffffffffffffffffffffffffe00000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5ef145766eca849f5d011536a6557fdb
+
+COUNT = 159
+KEY = ffffffffffffffffffffffffffffffffffffffff00000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c9af27b2c89c9b4cf4a0c4106ac80318
+
+COUNT = 160
+KEY = ffffffffffffffffffffffffffffffffffffffff80000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fb9c4f16c621f4eab7e9ac1d7551dd57
+
+COUNT = 161
+KEY = ffffffffffffffffffffffffffffffffffffffffc0000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 138e06fba466fa70854d8c2e524cffb2
+
+COUNT = 162
+KEY = ffffffffffffffffffffffffffffffffffffffffe0000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fb4bc78b225070773f04c40466d4e90c
+
+COUNT = 163
+KEY = fffffffffffffffffffffffffffffffffffffffff0000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8b2cbff1ed0150feda8a4799be94551f
+
+COUNT = 164
+KEY = fffffffffffffffffffffffffffffffffffffffff8000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 08b30d7b3f27962709a36bcadfb974bd
+
+COUNT = 165
+KEY = fffffffffffffffffffffffffffffffffffffffffc000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fdf6d32e044d77adcf37fb97ac213326
+
+COUNT = 166
+KEY = fffffffffffffffffffffffffffffffffffffffffe000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 93cb284ecdcfd781a8afe32077949e88
+
+COUNT = 167
+KEY = ffffffffffffffffffffffffffffffffffffffffff000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7b017bb02ec87b2b94c96e40a26fc71a
+
+COUNT = 168
+KEY = ffffffffffffffffffffffffffffffffffffffffff800000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c5c038b6990664ab08a3aaa5df9f3266
+
+COUNT = 169
+KEY = ffffffffffffffffffffffffffffffffffffffffffc00000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4b7020be37fab6259b2a27f4ec551576
+
+COUNT = 170
+KEY = ffffffffffffffffffffffffffffffffffffffffffe00000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 60136703374f64e860b48ce31f930716
+
+COUNT = 171
+KEY = fffffffffffffffffffffffffffffffffffffffffff00000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8d63a269b14d506ccc401ab8a9f1b591
+
+COUNT = 172
+KEY = fffffffffffffffffffffffffffffffffffffffffff80000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d317f81dc6aa454aee4bd4a5a5cff4bd
+
+COUNT = 173
+KEY = fffffffffffffffffffffffffffffffffffffffffffc0000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = dddececd5354f04d530d76ed884246eb
+
+COUNT = 174
+KEY = fffffffffffffffffffffffffffffffffffffffffffe0000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 41c5205cc8fd8eda9a3cffd2518f365a
+
+COUNT = 175
+KEY = ffffffffffffffffffffffffffffffffffffffffffff0000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cf42fb474293d96eca9db1b37b1ba676
+
+COUNT = 176
+KEY = ffffffffffffffffffffffffffffffffffffffffffff8000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a231692607169b4ecdead5cd3b10db3e
+
+COUNT = 177
+KEY = ffffffffffffffffffffffffffffffffffffffffffffc000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ace4b91c9c669e77e7acacd19859ed49
+
+COUNT = 178
+KEY = ffffffffffffffffffffffffffffffffffffffffffffe000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 75db7cfd4a7b2b62ab78a48f3ddaf4af
+
+COUNT = 179
+KEY = fffffffffffffffffffffffffffffffffffffffffffff000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c1faba2d46e259cf480d7c38e4572a58
+
+COUNT = 180
+KEY = fffffffffffffffffffffffffffffffffffffffffffff800
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 241c45bc6ae16dee6eb7bea128701582
+
+COUNT = 181
+KEY = fffffffffffffffffffffffffffffffffffffffffffffc00
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8fd03057cf1364420c2b78069a3e2502
+
+COUNT = 182
+KEY = fffffffffffffffffffffffffffffffffffffffffffffe00
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ddb505e6cc1384cbaec1df90b80beb20
+
+COUNT = 183
+KEY = ffffffffffffffffffffffffffffffffffffffffffffff00
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5674a3bed27bf4bd3622f9f5fe208306
+
+COUNT = 184
+KEY = ffffffffffffffffffffffffffffffffffffffffffffff80
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b687f26a89cfbfbb8e5eeac54055315e
+
+COUNT = 185
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffc0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 0547dd32d3b29ab6a4caeb606c5b6f78
+
+COUNT = 186
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffe0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 186861f8bc5386d31fb77f720c3226e6
+
+COUNT = 187
+KEY = fffffffffffffffffffffffffffffffffffffffffffffff0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = eacf1e6c4224efb38900b185ab1dfd42
+
+COUNT = 188
+KEY = fffffffffffffffffffffffffffffffffffffffffffffff8
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d241aab05a42d319de81d874f5c7b90d
+
+COUNT = 189
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffc
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5eb9bc759e2ad8d2140a6c762ae9e1ab
+
+COUNT = 190
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffe
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 018596e15e78e2c064159defce5f3085
+
+COUNT = 191
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffff
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = dd8a493514231cbf56eccee4c40889fb
+
+
+ECB Varying Plaintext 256 bits
+
+COUNT = 0
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 80000000000000000000000000000000
+CIPHERTEXT = ddc6bf790c15760d8d9aeb6f9a75fd4e
+
+COUNT = 1
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = c0000000000000000000000000000000
+CIPHERTEXT = 0a6bdc6d4c1e6280301fd8e97ddbe601
+
+COUNT = 2
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = e0000000000000000000000000000000
+CIPHERTEXT = 9b80eefb7ebe2d2b16247aa0efc72f5d
+
+COUNT = 3
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = f0000000000000000000000000000000
+CIPHERTEXT = 7f2c5ece07a98d8bee13c51177395ff7
+
+COUNT = 4
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = f8000000000000000000000000000000
+CIPHERTEXT = 7818d800dcf6f4be1e0e94f403d1e4c2
+
+COUNT = 5
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fc000000000000000000000000000000
+CIPHERTEXT = e74cd1c92f0919c35a0324123d6177d3
+
+COUNT = 6
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fe000000000000000000000000000000
+CIPHERTEXT = 8092a4dcf2da7e77e93bdd371dfed82e
+
+COUNT = 7
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ff000000000000000000000000000000
+CIPHERTEXT = 49af6b372135acef10132e548f217b17
+
+COUNT = 8
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ff800000000000000000000000000000
+CIPHERTEXT = 8bcd40f94ebb63b9f7909676e667f1e7
+
+COUNT = 9
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffc00000000000000000000000000000
+CIPHERTEXT = fe1cffb83f45dcfb38b29be438dbd3ab
+
+COUNT = 10
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffe00000000000000000000000000000
+CIPHERTEXT = 0dc58a8d886623705aec15cb1e70dc0e
+
+COUNT = 11
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fff00000000000000000000000000000
+CIPHERTEXT = c218faa16056bd0774c3e8d79c35a5e4
+
+COUNT = 12
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fff80000000000000000000000000000
+CIPHERTEXT = 047bba83f7aa841731504e012208fc9e
+
+COUNT = 13
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffc0000000000000000000000000000
+CIPHERTEXT = dc8f0e4915fd81ba70a331310882f6da
+
+COUNT = 14
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffe0000000000000000000000000000
+CIPHERTEXT = 1569859ea6b7206c30bf4fd0cbfac33c
+
+COUNT = 15
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffff0000000000000000000000000000
+CIPHERTEXT = 300ade92f88f48fa2df730ec16ef44cd
+
+COUNT = 16
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffff8000000000000000000000000000
+CIPHERTEXT = 1fe6cc3c05965dc08eb0590c95ac71d0
+
+COUNT = 17
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffc000000000000000000000000000
+CIPHERTEXT = 59e858eaaa97fec38111275b6cf5abc0
+
+COUNT = 18
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffe000000000000000000000000000
+CIPHERTEXT = 2239455e7afe3b0616100288cc5a723b
+
+COUNT = 19
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffff000000000000000000000000000
+CIPHERTEXT = 3ee500c5c8d63479717163e55c5c4522
+
+COUNT = 20
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffff800000000000000000000000000
+CIPHERTEXT = d5e38bf15f16d90e3e214041d774daa8
+
+COUNT = 21
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffc00000000000000000000000000
+CIPHERTEXT = b1f4066e6f4f187dfe5f2ad1b17819d0
+
+COUNT = 22
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffe00000000000000000000000000
+CIPHERTEXT = 6ef4cc4de49b11065d7af2909854794a
+
+COUNT = 23
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffff00000000000000000000000000
+CIPHERTEXT = ac86bc606b6640c309e782f232bf367f
+
+COUNT = 24
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffff80000000000000000000000000
+CIPHERTEXT = 36aff0ef7bf3280772cf4cac80a0d2b2
+
+COUNT = 25
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffc0000000000000000000000000
+CIPHERTEXT = 1f8eedea0f62a1406d58cfc3ecea72cf
+
+COUNT = 26
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffe0000000000000000000000000
+CIPHERTEXT = abf4154a3375a1d3e6b1d454438f95a6
+
+COUNT = 27
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffff0000000000000000000000000
+CIPHERTEXT = 96f96e9d607f6615fc192061ee648b07
+
+COUNT = 28
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffff8000000000000000000000000
+CIPHERTEXT = cf37cdaaa0d2d536c71857634c792064
+
+COUNT = 29
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffc000000000000000000000000
+CIPHERTEXT = fbd6640c80245c2b805373f130703127
+
+COUNT = 30
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffe000000000000000000000000
+CIPHERTEXT = 8d6a8afe55a6e481badae0d146f436db
+
+COUNT = 31
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffff000000000000000000000000
+CIPHERTEXT = 6a4981f2915e3e68af6c22385dd06756
+
+COUNT = 32
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffff800000000000000000000000
+CIPHERTEXT = 42a1136e5f8d8d21d3101998642d573b
+
+COUNT = 33
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffc00000000000000000000000
+CIPHERTEXT = 9b471596dc69ae1586cee6158b0b0181
+
+COUNT = 34
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffe00000000000000000000000
+CIPHERTEXT = 753665c4af1eff33aa8b628bf8741cfd
+
+COUNT = 35
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffff00000000000000000000000
+CIPHERTEXT = 9a682acf40be01f5b2a4193c9a82404d
+
+COUNT = 36
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffff80000000000000000000000
+CIPHERTEXT = 54fafe26e4287f17d1935f87eb9ade01
+
+COUNT = 37
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffc0000000000000000000000
+CIPHERTEXT = 49d541b2e74cfe73e6a8e8225f7bd449
+
+COUNT = 38
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffe0000000000000000000000
+CIPHERTEXT = 11a45530f624ff6f76a1b3826626ff7b
+
+COUNT = 39
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffff0000000000000000000000
+CIPHERTEXT = f96b0c4a8bc6c86130289f60b43b8fba
+
+COUNT = 40
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffff8000000000000000000000
+CIPHERTEXT = 48c7d0e80834ebdc35b6735f76b46c8b
+
+COUNT = 41
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffc000000000000000000000
+CIPHERTEXT = 2463531ab54d66955e73edc4cb8eaa45
+
+COUNT = 42
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffe000000000000000000000
+CIPHERTEXT = ac9bd8e2530469134b9d5b065d4f565b
+
+COUNT = 43
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffff000000000000000000000
+CIPHERTEXT = 3f5f9106d0e52f973d4890e6f37e8a00
+
+COUNT = 44
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffff800000000000000000000
+CIPHERTEXT = 20ebc86f1304d272e2e207e59db639f0
+
+COUNT = 45
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffc00000000000000000000
+CIPHERTEXT = e67ae6426bf9526c972cff072b52252c
+
+COUNT = 46
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffe00000000000000000000
+CIPHERTEXT = 1a518dddaf9efa0d002cc58d107edfc8
+
+COUNT = 47
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffff00000000000000000000
+CIPHERTEXT = ead731af4d3a2fe3b34bed047942a49f
+
+COUNT = 48
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffff80000000000000000000
+CIPHERTEXT = b1d4efe40242f83e93b6c8d7efb5eae9
+
+COUNT = 49
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffc0000000000000000000
+CIPHERTEXT = cd2b1fec11fd906c5c7630099443610a
+
+COUNT = 50
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffe0000000000000000000
+CIPHERTEXT = a1853fe47fe29289d153161d06387d21
+
+COUNT = 51
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffff0000000000000000000
+CIPHERTEXT = 4632154179a555c17ea604d0889fab14
+
+COUNT = 52
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffff8000000000000000000
+CIPHERTEXT = dd27cac6401a022e8f38f9f93e774417
+
+COUNT = 53
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffc000000000000000000
+CIPHERTEXT = c090313eb98674f35f3123385fb95d4d
+
+COUNT = 54
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffe000000000000000000
+CIPHERTEXT = cc3526262b92f02edce548f716b9f45c
+
+COUNT = 55
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffff000000000000000000
+CIPHERTEXT = c0838d1a2b16a7c7f0dfcc433c399c33
+
+COUNT = 56
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffff800000000000000000
+CIPHERTEXT = 0d9ac756eb297695eed4d382eb126d26
+
+COUNT = 57
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffc00000000000000000
+CIPHERTEXT = 56ede9dda3f6f141bff1757fa689c3e1
+
+COUNT = 58
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffe00000000000000000
+CIPHERTEXT = 768f520efe0f23e61d3ec8ad9ce91774
+
+COUNT = 59
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffff00000000000000000
+CIPHERTEXT = b1144ddfa75755213390e7c596660490
+
+COUNT = 60
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffff80000000000000000
+CIPHERTEXT = 1d7c0c4040b355b9d107a99325e3b050
+
+COUNT = 61
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffc0000000000000000
+CIPHERTEXT = d8e2bb1ae8ee3dcf5bf7d6c38da82a1a
+
+COUNT = 62
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffe0000000000000000
+CIPHERTEXT = faf82d178af25a9886a47e7f789b98d7
+
+COUNT = 63
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffff0000000000000000
+CIPHERTEXT = 9b58dbfd77fe5aca9cfc190cd1b82d19
+
+COUNT = 64
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffff8000000000000000
+CIPHERTEXT = 77f392089042e478ac16c0c86a0b5db5
+
+COUNT = 65
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffc000000000000000
+CIPHERTEXT = 19f08e3420ee69b477ca1420281c4782
+
+COUNT = 66
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffe000000000000000
+CIPHERTEXT = a1b19beee4e117139f74b3c53fdcb875
+
+COUNT = 67
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffff000000000000000
+CIPHERTEXT = a37a5869b218a9f3a0868d19aea0ad6a
+
+COUNT = 68
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffff800000000000000
+CIPHERTEXT = bc3594e865bcd0261b13202731f33580
+
+COUNT = 69
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffc00000000000000
+CIPHERTEXT = 811441ce1d309eee7185e8c752c07557
+
+COUNT = 70
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffe00000000000000
+CIPHERTEXT = 959971ce4134190563518e700b9874d1
+
+COUNT = 71
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffff00000000000000
+CIPHERTEXT = 76b5614a042707c98e2132e2e805fe63
+
+COUNT = 72
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffff80000000000000
+CIPHERTEXT = 7d9fa6a57530d0f036fec31c230b0cc6
+
+COUNT = 73
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffc0000000000000
+CIPHERTEXT = 964153a83bf6989a4ba80daa91c3e081
+
+COUNT = 74
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffe0000000000000
+CIPHERTEXT = a013014d4ce8054cf2591d06f6f2f176
+
+COUNT = 75
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffff0000000000000
+CIPHERTEXT = d1c5f6399bf382502e385eee1474a869
+
+COUNT = 76
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffff8000000000000
+CIPHERTEXT = 0007e20b8298ec354f0f5fe7470f36bd
+
+COUNT = 77
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffc000000000000
+CIPHERTEXT = b95ba05b332da61ef63a2b31fcad9879
+
+COUNT = 78
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffe000000000000
+CIPHERTEXT = 4620a49bd967491561669ab25dce45f4
+
+COUNT = 79
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffff000000000000
+CIPHERTEXT = 12e71214ae8e04f0bb63d7425c6f14d5
+
+COUNT = 80
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffff800000000000
+CIPHERTEXT = 4cc42fc1407b008fe350907c092e80ac
+
+COUNT = 81
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffc00000000000
+CIPHERTEXT = 08b244ce7cbc8ee97fbba808cb146fda
+
+COUNT = 82
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffe00000000000
+CIPHERTEXT = 39b333e8694f21546ad1edd9d87ed95b
+
+COUNT = 83
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffff00000000000
+CIPHERTEXT = 3b271f8ab2e6e4a20ba8090f43ba78f3
+
+COUNT = 84
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffff80000000000
+CIPHERTEXT = 9ad983f3bf651cd0393f0a73cccdea50
+
+COUNT = 85
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffc0000000000
+CIPHERTEXT = 8f476cbff75c1f725ce18e4bbcd19b32
+
+COUNT = 86
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffe0000000000
+CIPHERTEXT = 905b6267f1d6ab5320835a133f096f2a
+
+COUNT = 87
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffff0000000000
+CIPHERTEXT = 145b60d6d0193c23f4221848a892d61a
+
+COUNT = 88
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffff8000000000
+CIPHERTEXT = 55cfb3fb6d75cad0445bbc8dafa25b0f
+
+COUNT = 89
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffc000000000
+CIPHERTEXT = 7b8e7098e357ef71237d46d8b075b0f5
+
+COUNT = 90
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffe000000000
+CIPHERTEXT = 2bf27229901eb40f2df9d8398d1505ae
+
+COUNT = 91
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffff000000000
+CIPHERTEXT = 83a63402a77f9ad5c1e931a931ecd706
+
+COUNT = 92
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffff800000000
+CIPHERTEXT = 6f8ba6521152d31f2bada1843e26b973
+
+COUNT = 93
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffc00000000
+CIPHERTEXT = e5c3b8e30fd2d8e6239b17b44bd23bbd
+
+COUNT = 94
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffe00000000
+CIPHERTEXT = 1ac1f7102c59933e8b2ddc3f14e94baa
+
+COUNT = 95
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffff00000000
+CIPHERTEXT = 21d9ba49f276b45f11af8fc71a088e3d
+
+COUNT = 96
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffff80000000
+CIPHERTEXT = 649f1cddc3792b4638635a392bc9bade
+
+COUNT = 97
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffc0000000
+CIPHERTEXT = e2775e4b59c1bc2e31a2078c11b5a08c
+
+COUNT = 98
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffe0000000
+CIPHERTEXT = 2be1fae5048a25582a679ca10905eb80
+
+COUNT = 99
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffff0000000
+CIPHERTEXT = da86f292c6f41ea34fb2068df75ecc29
+
+COUNT = 100
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffff8000000
+CIPHERTEXT = 220df19f85d69b1b562fa69a3c5beca5
+
+COUNT = 101
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffc000000
+CIPHERTEXT = 1f11d5d0355e0b556ccdb6c7f5083b4d
+
+COUNT = 102
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffe000000
+CIPHERTEXT = 62526b78be79cb384633c91f83b4151b
+
+COUNT = 103
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffff000000
+CIPHERTEXT = 90ddbcb950843592dd47bbef00fdc876
+
+COUNT = 104
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffff800000
+CIPHERTEXT = 2fd0e41c5b8402277354a7391d2618e2
+
+COUNT = 105
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffc00000
+CIPHERTEXT = 3cdf13e72dee4c581bafec70b85f9660
+
+COUNT = 106
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffe00000
+CIPHERTEXT = afa2ffc137577092e2b654fa199d2c43
+
+COUNT = 107
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffff00000
+CIPHERTEXT = 8d683ee63e60d208e343ce48dbc44cac
+
+COUNT = 108
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffff80000
+CIPHERTEXT = 705a4ef8ba2133729c20185c3d3a4763
+
+COUNT = 109
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffc0000
+CIPHERTEXT = 0861a861c3db4e94194211b77ed761b9
+
+COUNT = 110
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffe0000
+CIPHERTEXT = 4b00c27e8b26da7eab9d3a88dec8b031
+
+COUNT = 111
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffff0000
+CIPHERTEXT = 5f397bf03084820cc8810d52e5b666e9
+
+COUNT = 112
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffff8000
+CIPHERTEXT = 63fafabb72c07bfbd3ddc9b1203104b8
+
+COUNT = 113
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffc000
+CIPHERTEXT = 683e2140585b18452dd4ffbb93c95df9
+
+COUNT = 114
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffe000
+CIPHERTEXT = 286894e48e537f8763b56707d7d155c8
+
+COUNT = 115
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffff000
+CIPHERTEXT = a423deabc173dcf7e2c4c53e77d37cd1
+
+COUNT = 116
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffff800
+CIPHERTEXT = eb8168313e1cfdfdb5e986d5429cf172
+
+COUNT = 117
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffc00
+CIPHERTEXT = 27127daafc9accd2fb334ec3eba52323
+
+COUNT = 118
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffe00
+CIPHERTEXT = ee0715b96f72e3f7a22a5064fc592f4c
+
+COUNT = 119
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffff00
+CIPHERTEXT = 29ee526770f2a11dcfa989d1ce88830f
+
+COUNT = 120
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffff80
+CIPHERTEXT = 0493370e054b09871130fe49af730a5a
+
+COUNT = 121
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffffc0
+CIPHERTEXT = 9b7b940f6c509f9e44a4ee140448ee46
+
+COUNT = 122
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffffe0
+CIPHERTEXT = 2915be4a1ecfdcbe3e023811a12bb6c7
+
+COUNT = 123
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffff0
+CIPHERTEXT = 7240e524bc51d8c4d440b1be55d1062c
+
+COUNT = 124
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffff8
+CIPHERTEXT = da63039d38cb4612b2dc36ba26684b93
+
+COUNT = 125
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffffc
+CIPHERTEXT = 0f59cb5a4b522e2ac56c1a64f558ad9a
+
+COUNT = 126
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffffe
+CIPHERTEXT = 7bfe9d876c6d63c1d035da8fe21c409d
+
+COUNT = 127
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffffff
+CIPHERTEXT = acdace8078a32b1a182bfa4987ca1347
+
+
+ECB Varying Key 256 bits
+
+COUNT = 0
+KEY = 8000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e35a6dcb19b201a01ebcfa8aa22b5759
+
+COUNT = 1
+KEY = c000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b29169cdcf2d83e838125a12ee6aa400
+
+COUNT = 2
+KEY = e000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d8f3a72fc3cdf74dfaf6c3e6b97b2fa6
+
+COUNT = 3
+KEY = f000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1c777679d50037c79491a94da76a9a35
+
+COUNT = 4
+KEY = f800000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9cf4893ecafa0a0247a898e040691559
+
+COUNT = 5
+KEY = fc00000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8fbb413703735326310a269bd3aa94b2
+
+COUNT = 6
+KEY = fe00000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 60e32246bed2b0e859e55c1cc6b26502
+
+COUNT = 7
+KEY = ff00000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ec52a212f80a09df6317021bc2a9819e
+
+COUNT = 8
+KEY = ff80000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f23e5b600eb70dbccf6c0b1d9a68182c
+
+COUNT = 9
+KEY = ffc0000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a3f599d63a82a968c33fe26590745970
+
+COUNT = 10
+KEY = ffe0000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d1ccb9b1337002cbac42c520b5d67722
+
+COUNT = 11
+KEY = fff0000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cc111f6c37cf40a1159d00fb59fb0488
+
+COUNT = 12
+KEY = fff8000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = dc43b51ab609052372989a26e9cdd714
+
+COUNT = 13
+KEY = fffc000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4dcede8da9e2578f39703d4433dc6459
+
+COUNT = 14
+KEY = fffe000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1a4c1c263bbccfafc11782894685e3a8
+
+COUNT = 15
+KEY = ffff000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 937ad84880db50613423d6d527a2823d
+
+COUNT = 16
+KEY = ffff800000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 610b71dfc688e150d8152c5b35ebc14d
+
+COUNT = 17
+KEY = ffffc00000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 27ef2495dabf323885aab39c80f18d8b
+
+COUNT = 18
+KEY = ffffe00000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 633cafea395bc03adae3a1e2068e4b4e
+
+COUNT = 19
+KEY = fffff00000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6e1b482b53761cf631819b749a6f3724
+
+COUNT = 20
+KEY = fffff80000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 976e6f851ab52c771998dbb2d71c75a9
+
+COUNT = 21
+KEY = fffffc0000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 85f2ba84f8c307cf525e124c3e22e6cc
+
+COUNT = 22
+KEY = fffffe0000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6bcca98bf6a835fa64955f72de4115fe
+
+COUNT = 23
+KEY = ffffff0000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2c75e2d36eebd65411f14fd0eb1d2a06
+
+COUNT = 24
+KEY = ffffff8000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bd49295006250ffca5100b6007a0eade
+
+COUNT = 25
+KEY = ffffffc000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a190527d0ef7c70f459cd3940df316ec
+
+COUNT = 26
+KEY = ffffffe000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bbd1097a62433f79449fa97d4ee80dbf
+
+COUNT = 27
+KEY = fffffff000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 07058e408f5b99b0e0f061a1761b5b3b
+
+COUNT = 28
+KEY = fffffff800000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5fd1f13fa0f31e37fabde328f894eac2
+
+COUNT = 29
+KEY = fffffffc00000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fc4af7c948df26e2ef3e01c1ee5b8f6f
+
+COUNT = 30
+KEY = fffffffe00000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 829fd7208fb92d44a074a677ee9861ac
+
+COUNT = 31
+KEY = ffffffff00000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ad9fc613a703251b54c64a0e76431711
+
+COUNT = 32
+KEY = ffffffff80000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 33ac9eccc4cc75e2711618f80b1548e8
+
+COUNT = 33
+KEY = ffffffffc0000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2025c74b8ad8f4cda17ee2049c4c902d
+
+COUNT = 34
+KEY = ffffffffe0000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f85ca05fe528f1ce9b790166e8d551e7
+
+COUNT = 35
+KEY = fffffffff0000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6f6238d8966048d4967154e0dad5a6c9
+
+COUNT = 36
+KEY = fffffffff8000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f2b21b4e7640a9b3346de8b82fb41e49
+
+COUNT = 37
+KEY = fffffffffc000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f836f251ad1d11d49dc344628b1884e1
+
+COUNT = 38
+KEY = fffffffffe000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 077e9470ae7abea5a9769d49182628c3
+
+COUNT = 39
+KEY = ffffffffff000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e0dcc2d27fc9865633f85223cf0d611f
+
+COUNT = 40
+KEY = ffffffffff800000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = be66cfea2fecd6bf0ec7b4352c99bcaa
+
+COUNT = 41
+KEY = ffffffffffc00000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = df31144f87a2ef523facdcf21a427804
+
+COUNT = 42
+KEY = ffffffffffe00000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b5bb0f5629fb6aae5e1839a3c3625d63
+
+COUNT = 43
+KEY = fffffffffff00000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3c9db3335306fe1ec612bdbfae6b6028
+
+COUNT = 44
+KEY = fffffffffff80000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3dd5c34634a79d3cfcc8339760e6f5f4
+
+COUNT = 45
+KEY = fffffffffffc0000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 82bda118a3ed7af314fa2ccc5c07b761
+
+COUNT = 46
+KEY = fffffffffffe0000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2937a64f7d4f46fe6fea3b349ec78e38
+
+COUNT = 47
+KEY = ffffffffffff0000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 225f068c28476605735ad671bb8f39f3
+
+COUNT = 48
+KEY = ffffffffffff8000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ae682c5ecd71898e08942ac9aa89875c
+
+COUNT = 49
+KEY = ffffffffffffc000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5e031cb9d676c3022d7f26227e85c38f
+
+COUNT = 50
+KEY = ffffffffffffe000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a78463fb064db5d52bb64bfef64f2dda
+
+COUNT = 51
+KEY = fffffffffffff000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8aa9b75e784593876c53a00eae5af52b
+
+COUNT = 52
+KEY = fffffffffffff800000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3f84566df23da48af692722fe980573a
+
+COUNT = 53
+KEY = fffffffffffffc00000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 31690b5ed41c7eb42a1e83270a7ff0e6
+
+COUNT = 54
+KEY = fffffffffffffe00000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 77dd7702646d55f08365e477d3590eda
+
+COUNT = 55
+KEY = ffffffffffffff00000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4c022ac62b3cb78d739cc67b3e20bb7e
+
+COUNT = 56
+KEY = ffffffffffffff80000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 092fa137ce18b5dfe7906f550bb13370
+
+COUNT = 57
+KEY = ffffffffffffffc0000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3e0cdadf2e68353c0027672c97144dd3
+
+COUNT = 58
+KEY = ffffffffffffffe0000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d8c4b200b383fc1f2b2ea677618a1d27
+
+COUNT = 59
+KEY = fffffffffffffff0000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 11825f99b0e9bb3477c1c0713b015aac
+
+COUNT = 60
+KEY = fffffffffffffff8000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f8b9fffb5c187f7ddc7ab10f4fb77576
+
+COUNT = 61
+KEY = fffffffffffffffc000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ffb4e87a32b37d6f2c8328d3b5377802
+
+COUNT = 62
+KEY = fffffffffffffffe000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d276c13a5d220f4da9224e74896391ce
+
+COUNT = 63
+KEY = ffffffffffffffff000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 94efe7a0e2e031e2536da01df799c927
+
+COUNT = 64
+KEY = ffffffffffffffff800000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8f8fd822680a85974e53a5a8eb9d38de
+
+COUNT = 65
+KEY = ffffffffffffffffc00000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e0f0a91b2e45f8cc37b7805a3042588d
+
+COUNT = 66
+KEY = ffffffffffffffffe00000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 597a6252255e46d6364dbeeda31e279c
+
+COUNT = 67
+KEY = fffffffffffffffff00000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f51a0f694442b8f05571797fec7ee8bf
+
+COUNT = 68
+KEY = fffffffffffffffff80000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9ff071b165b5198a93dddeebc54d09b5
+
+COUNT = 69
+KEY = fffffffffffffffffc0000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c20a19fd5758b0c4bc1a5df89cf73877
+
+COUNT = 70
+KEY = fffffffffffffffffe0000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 97120166307119ca2280e9315668e96f
+
+COUNT = 71
+KEY = ffffffffffffffffff0000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4b3b9f1e099c2a09dc091e90e4f18f0a
+
+COUNT = 72
+KEY = ffffffffffffffffff8000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = eb040b891d4b37f6851f7ec219cd3f6d
+
+COUNT = 73
+KEY = ffffffffffffffffffc000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9f0fdec08b7fd79aa39535bea42db92a
+
+COUNT = 74
+KEY = ffffffffffffffffffe000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2e70f168fc74bf911df240bcd2cef236
+
+COUNT = 75
+KEY = fffffffffffffffffff000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 462ccd7f5fd1108dbc152f3cacad328b
+
+COUNT = 76
+KEY = fffffffffffffffffff800000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a4af534a7d0b643a01868785d86dfb95
+
+COUNT = 77
+KEY = fffffffffffffffffffc00000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ab980296197e1a5022326c31da4bf6f3
+
+COUNT = 78
+KEY = fffffffffffffffffffe00000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f97d57b3333b6281b07d486db2d4e20c
+
+COUNT = 79
+KEY = ffffffffffffffffffff00000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f33fa36720231afe4c759ade6bd62eb6
+
+COUNT = 80
+KEY = ffffffffffffffffffff80000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fdcfac0c02ca538343c68117e0a15938
+
+COUNT = 81
+KEY = ffffffffffffffffffffc0000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ad4916f5ee5772be764fc027b8a6e539
+
+COUNT = 82
+KEY = ffffffffffffffffffffe0000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2e16873e1678610d7e14c02d002ea845
+
+COUNT = 83
+KEY = fffffffffffffffffffff0000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4e6e627c1acc51340053a8236d579576
+
+COUNT = 84
+KEY = fffffffffffffffffffff8000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ab0c8410aeeead92feec1eb430d652cb
+
+COUNT = 85
+KEY = fffffffffffffffffffffc000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e86f7e23e835e114977f60e1a592202e
+
+COUNT = 86
+KEY = fffffffffffffffffffffe000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e68ad5055a367041fade09d9a70a794b
+
+COUNT = 87
+KEY = ffffffffffffffffffffff000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 0791823a3c666bb6162825e78606a7fe
+
+COUNT = 88
+KEY = ffffffffffffffffffffff800000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = dcca366a9bf47b7b868b77e25c18a364
+
+COUNT = 89
+KEY = ffffffffffffffffffffffc00000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 684c9efc237e4a442965f84bce20247a
+
+COUNT = 90
+KEY = ffffffffffffffffffffffe00000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a858411ffbe63fdb9c8aa1bfaed67b52
+
+COUNT = 91
+KEY = fffffffffffffffffffffff00000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 04bc3da2179c3015498b0e03910db5b8
+
+COUNT = 92
+KEY = fffffffffffffffffffffff80000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 40071eeab3f935dbc25d00841460260f
+
+COUNT = 93
+KEY = fffffffffffffffffffffffc0000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 0ebd7c30ed2016e08ba806ddb008bcc8
+
+COUNT = 94
+KEY = fffffffffffffffffffffffe0000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 15c6becf0f4cec7129cbd22d1a79b1b8
+
+COUNT = 95
+KEY = ffffffffffffffffffffffff0000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 0aeede5b91f721700e9e62edbf60b781
+
+COUNT = 96
+KEY = ffffffffffffffffffffffff8000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 266581af0dcfbed1585e0a242c64b8df
+
+COUNT = 97
+KEY = ffffffffffffffffffffffffc000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6693dc911662ae473216ba22189a511a
+
+COUNT = 98
+KEY = ffffffffffffffffffffffffe000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7606fa36d86473e6fb3a1bb0e2c0adf5
+
+COUNT = 99
+KEY = fffffffffffffffffffffffff000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 112078e9e11fbb78e26ffb8899e96b9a
+
+COUNT = 100
+KEY = fffffffffffffffffffffffff800000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 40b264e921e9e4a82694589ef3798262
+
+COUNT = 101
+KEY = fffffffffffffffffffffffffc00000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8d4595cb4fa7026715f55bd68e2882f9
+
+COUNT = 102
+KEY = fffffffffffffffffffffffffe00000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b588a302bdbc09197df1edae68926ed9
+
+COUNT = 103
+KEY = ffffffffffffffffffffffffff00000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 33f7502390b8a4a221cfecd0666624ba
+
+COUNT = 104
+KEY = ffffffffffffffffffffffffff80000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3d20253adbce3be2373767c4d822c566
+
+COUNT = 105
+KEY = ffffffffffffffffffffffffffc0000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a42734a3929bf84cf0116c9856a3c18c
+
+COUNT = 106
+KEY = ffffffffffffffffffffffffffe0000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e3abc4939457422bb957da3c56938c6d
+
+COUNT = 107
+KEY = fffffffffffffffffffffffffff0000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 972bdd2e7c525130fadc8f76fc6f4b3f
+
+COUNT = 108
+KEY = fffffffffffffffffffffffffff8000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 84a83d7b94c699cbcb8a7d9b61f64093
+
+COUNT = 109
+KEY = fffffffffffffffffffffffffffc000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ce61d63514aded03d43e6ebfc3a9001f
+
+COUNT = 110
+KEY = fffffffffffffffffffffffffffe000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6c839dd58eeae6b8a36af48ed63d2dc9
+
+COUNT = 111
+KEY = ffffffffffffffffffffffffffff000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cd5ece55b8da3bf622c4100df5de46f9
+
+COUNT = 112
+KEY = ffffffffffffffffffffffffffff800000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3b6f46f40e0ac5fc0a9c1105f800f48d
+
+COUNT = 113
+KEY = ffffffffffffffffffffffffffffc00000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ba26d47da3aeb028de4fb5b3a854a24b
+
+COUNT = 114
+KEY = ffffffffffffffffffffffffffffe00000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 87f53bf620d3677268445212904389d5
+
+COUNT = 115
+KEY = fffffffffffffffffffffffffffff00000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 10617d28b5e0f4605492b182a5d7f9f6
+
+COUNT = 116
+KEY = fffffffffffffffffffffffffffff80000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9aaec4fabbf6fae2a71feff02e372b39
+
+COUNT = 117
+KEY = fffffffffffffffffffffffffffffc0000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3a90c62d88b5c42809abf782488ed130
+
+COUNT = 118
+KEY = fffffffffffffffffffffffffffffe0000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f1f1c5a40899e15772857ccb65c7a09a
+
+COUNT = 119
+KEY = ffffffffffffffffffffffffffffff0000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 190843d29b25a3897c692ce1dd81ee52
+
+COUNT = 120
+KEY = ffffffffffffffffffffffffffffff8000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a866bc65b6941d86e8420a7ffb0964db
+
+COUNT = 121
+KEY = ffffffffffffffffffffffffffffffc000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8193c6ff85225ced4255e92f6e078a14
+
+COUNT = 122
+KEY = ffffffffffffffffffffffffffffffe000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9661cb2424d7d4a380d547f9e7ec1cb9
+
+COUNT = 123
+KEY = fffffffffffffffffffffffffffffff000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 86f93d9ec08453a071e2e2877877a9c8
+
+COUNT = 124
+KEY = fffffffffffffffffffffffffffffff800000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 27eefa80ce6a4a9d598e3fec365434d2
+
+COUNT = 125
+KEY = fffffffffffffffffffffffffffffffc00000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d62068444578e3ab39ce7ec95dd045dc
+
+COUNT = 126
+KEY = fffffffffffffffffffffffffffffffe00000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b5f71d4dd9a71fe5d8bc8ba7e6ea3048
+
+COUNT = 127
+KEY = ffffffffffffffffffffffffffffffff00000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6825a347ac479d4f9d95c5cb8d3fd7e9
+
+COUNT = 128
+KEY = ffffffffffffffffffffffffffffffff80000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e3714e94a5778955cc0346358e94783a
+
+COUNT = 129
+KEY = ffffffffffffffffffffffffffffffffc0000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d836b44bb29e0c7d89fa4b2d4b677d2a
+
+COUNT = 130
+KEY = ffffffffffffffffffffffffffffffffe0000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5d454b75021d76d4b84f873a8f877b92
+
+COUNT = 131
+KEY = fffffffffffffffffffffffffffffffff0000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c3498f7eced2095314fc28115885b33f
+
+COUNT = 132
+KEY = fffffffffffffffffffffffffffffffff8000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6e668856539ad8e405bd123fe6c88530
+
+COUNT = 133
+KEY = fffffffffffffffffffffffffffffffffc000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8680db7f3a87b8605543cfdbe6754076
+
+COUNT = 134
+KEY = fffffffffffffffffffffffffffffffffe000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6c5d03b13069c3658b3179be91b0800c
+
+COUNT = 135
+KEY = ffffffffffffffffffffffffffffffffff000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ef1b384ac4d93eda00c92add0995ea5f
+
+COUNT = 136
+KEY = ffffffffffffffffffffffffffffffffff800000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bf8115805471741bd5ad20a03944790f
+
+COUNT = 137
+KEY = ffffffffffffffffffffffffffffffffffc00000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c64c24b6894b038b3c0d09b1df068b0b
+
+COUNT = 138
+KEY = ffffffffffffffffffffffffffffffffffe00000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3967a10cffe27d0178545fbf6a40544b
+
+COUNT = 139
+KEY = fffffffffffffffffffffffffffffffffff00000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7c85e9c95de1a9ec5a5363a8a053472d
+
+COUNT = 140
+KEY = fffffffffffffffffffffffffffffffffff80000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a9eec03c8abec7ba68315c2c8c2316e0
+
+COUNT = 141
+KEY = fffffffffffffffffffffffffffffffffffc0000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cac8e414c2f388227ae14986fc983524
+
+COUNT = 142
+KEY = fffffffffffffffffffffffffffffffffffe0000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5d942b7f4622ce056c3ce3ce5f1dd9d6
+
+COUNT = 143
+KEY = ffffffffffffffffffffffffffffffffffff0000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d240d648ce21a3020282c3f1b528a0b6
+
+COUNT = 144
+KEY = ffffffffffffffffffffffffffffffffffff8000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 45d089c36d5c5a4efc689e3b0de10dd5
+
+COUNT = 145
+KEY = ffffffffffffffffffffffffffffffffffffc000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b4da5df4becb5462e03a0ed00d295629
+
+COUNT = 146
+KEY = ffffffffffffffffffffffffffffffffffffe000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = dcf4e129136c1a4b7a0f38935cc34b2b
+
+COUNT = 147
+KEY = fffffffffffffffffffffffffffffffffffff000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d9a4c7618b0ce48a3d5aee1a1c0114c4
+
+COUNT = 148
+KEY = fffffffffffffffffffffffffffffffffffff800000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ca352df025c65c7b0bf306fbee0f36ba
+
+COUNT = 149
+KEY = fffffffffffffffffffffffffffffffffffffc00000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 238aca23fd3409f38af63378ed2f5473
+
+COUNT = 150
+KEY = fffffffffffffffffffffffffffffffffffffe00000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 59836a0e06a79691b36667d5380d8188
+
+COUNT = 151
+KEY = ffffffffffffffffffffffffffffffffffffff00000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 33905080f7acf1cdae0a91fc3e85aee4
+
+COUNT = 152
+KEY = ffffffffffffffffffffffffffffffffffffff80000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 72c9e4646dbc3d6320fc6689d93e8833
+
+COUNT = 153
+KEY = ffffffffffffffffffffffffffffffffffffffc0000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ba77413dea5925b7f5417ea47ff19f59
+
+COUNT = 154
+KEY = ffffffffffffffffffffffffffffffffffffffe0000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6cae8129f843d86dc786a0fb1a184970
+
+COUNT = 155
+KEY = fffffffffffffffffffffffffffffffffffffff0000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fcfefb534100796eebbd990206754e19
+
+COUNT = 156
+KEY = fffffffffffffffffffffffffffffffffffffff8000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8c791d5fdddf470da04f3e6dc4a5b5b5
+
+COUNT = 157
+KEY = fffffffffffffffffffffffffffffffffffffffc000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c93bbdc07a4611ae4bb266ea5034a387
+
+COUNT = 158
+KEY = fffffffffffffffffffffffffffffffffffffffe000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c102e38e489aa74762f3efc5bb23205a
+
+COUNT = 159
+KEY = ffffffffffffffffffffffffffffffffffffffff000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 93201481665cbafc1fcc220bc545fb3d
+
+COUNT = 160
+KEY = ffffffffffffffffffffffffffffffffffffffff800000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4960757ec6ce68cf195e454cfd0f32ca
+
+COUNT = 161
+KEY = ffffffffffffffffffffffffffffffffffffffffc00000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = feec7ce6a6cbd07c043416737f1bbb33
+
+COUNT = 162
+KEY = ffffffffffffffffffffffffffffffffffffffffe00000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 11c5413904487a805d70a8edd9c35527
+
+COUNT = 163
+KEY = fffffffffffffffffffffffffffffffffffffffff00000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 347846b2b2e36f1f0324c86f7f1b98e2
+
+COUNT = 164
+KEY = fffffffffffffffffffffffffffffffffffffffff80000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 332eee1a0cbd19ca2d69b426894044f0
+
+COUNT = 165
+KEY = fffffffffffffffffffffffffffffffffffffffffc0000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 866b5b3977ba6efa5128efbda9ff03cd
+
+COUNT = 166
+KEY = fffffffffffffffffffffffffffffffffffffffffe0000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cc1445ee94c0f08cdee5c344ecd1e233
+
+COUNT = 167
+KEY = ffffffffffffffffffffffffffffffffffffffffff0000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = be288319029363c2622feba4b05dfdfe
+
+COUNT = 168
+KEY = ffffffffffffffffffffffffffffffffffffffffff8000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cfd1875523f3cd21c395651e6ee15e56
+
+COUNT = 169
+KEY = ffffffffffffffffffffffffffffffffffffffffffc000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cb5a408657837c53bf16f9d8465dce19
+
+COUNT = 170
+KEY = ffffffffffffffffffffffffffffffffffffffffffe000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ca0bf42cb107f55ccff2fc09ee08ca15
+
+COUNT = 171
+KEY = fffffffffffffffffffffffffffffffffffffffffff000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fdd9bbb4a7dc2e4a23536a5880a2db67
+
+COUNT = 172
+KEY = fffffffffffffffffffffffffffffffffffffffffff800000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ede447b362c484993dec9442a3b46aef
+
+COUNT = 173
+KEY = fffffffffffffffffffffffffffffffffffffffffffc00000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 10dffb05904bff7c4781df780ad26837
+
+COUNT = 174
+KEY = fffffffffffffffffffffffffffffffffffffffffffe00000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c33bc13e8de88ac25232aa7496398783
+
+COUNT = 175
+KEY = ffffffffffffffffffffffffffffffffffffffffffff00000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ca359c70803a3b2a3d542e8781dea975
+
+COUNT = 176
+KEY = ffffffffffffffffffffffffffffffffffffffffffff80000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bcc65b526f88d05b89ce8a52021fdb06
+
+COUNT = 177
+KEY = ffffffffffffffffffffffffffffffffffffffffffffc0000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = db91a38855c8c4643851fbfb358b0109
+
+COUNT = 178
+KEY = ffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ca6e8893a114ae8e27d5ab03a5499610
+
+COUNT = 179
+KEY = fffffffffffffffffffffffffffffffffffffffffffff0000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6629d2b8df97da728cdd8b1e7f945077
+
+COUNT = 180
+KEY = fffffffffffffffffffffffffffffffffffffffffffff8000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4570a5a18cfc0dd582f1d88d5c9a1720
+
+COUNT = 181
+KEY = fffffffffffffffffffffffffffffffffffffffffffffc000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 72bc65aa8e89562e3f274d45af1cd10b
+
+COUNT = 182
+KEY = fffffffffffffffffffffffffffffffffffffffffffffe000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 98551da1a6503276ae1c77625f9ea615
+
+COUNT = 183
+KEY = ffffffffffffffffffffffffffffffffffffffffffffff000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 0ddfe51ced7e3f4ae927daa3fe452cee
+
+COUNT = 184
+KEY = ffffffffffffffffffffffffffffffffffffffffffffff800000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = db826251e4ce384b80218b0e1da1dd4c
+
+COUNT = 185
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffc00000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2cacf728b88abbad7011ed0e64a1680c
+
+COUNT = 186
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffe00000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 330d8ee7c5677e099ac74c9994ee4cfb
+
+COUNT = 187
+KEY = fffffffffffffffffffffffffffffffffffffffffffffff00000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = edf61ae362e882ddc0167474a7a77f3a
+
+COUNT = 188
+KEY = fffffffffffffffffffffffffffffffffffffffffffffff80000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6168b00ba7859e0970ecfd757efecf7c
+
+COUNT = 189
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffc0000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d1415447866230d28bb1ea18a4cdfd02
+
+COUNT = 190
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 516183392f7a8763afec68a060264141
+
+COUNT = 191
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 77565c8d73cfd4130b4aa14d8911710f
+
+COUNT = 192
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffff8000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 37232a4ed21ccc27c19c9610078cabac
+
+COUNT = 193
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffc000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 804f32ea71828c7d329077e712231666
+
+COUNT = 194
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d64424f23cb97215e9c2c6f28d29eab7
+
+COUNT = 195
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 023e82b533f68c75c238cebdb2ee89a2
+
+COUNT = 196
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffff800000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 193a3d24157a51f1ee0893f6777417e7
+
+COUNT = 197
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffc00000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 84ecacfcd400084d078612b1945f2ef5
+
+COUNT = 198
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffe00000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1dcd8bb173259eb33a5242b0de31a455
+
+COUNT = 199
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 35e9eddbc375e792c19992c19165012b
+
+COUNT = 200
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8a772231c01dfdd7c98e4cfddcc0807a
+
+COUNT = 201
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffc0000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6eda7ff6b8319180ff0d6e65629d01c3
+
+COUNT = 202
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c267ef0e2d01a993944dd397101413cb
+
+COUNT = 203
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e9f80e9d845bcc0f62926af72eabca39
+
+COUNT = 204
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffff8000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6702990727aa0878637b45dcd3a3b074
+
+COUNT = 205
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffc000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2e2e647d5360e09230a5d738ca33471e
+
+COUNT = 206
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1f56413c7add6f43d1d56e4f02190330
+
+COUNT = 207
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 69cd0606e15af729d6bca143016d9842
+
+COUNT = 208
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffff800000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a085d7c1a500873a20099c4caa3c3f5b
+
+COUNT = 209
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffc00000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4fc0d230f8891415b87b83f95f2e09d1
+
+COUNT = 210
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4327d08c523d8eba697a4336507d1f42
+
+COUNT = 211
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7a15aab82701efa5ae36ab1d6b76290f
+
+COUNT = 212
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5bf0051893a18bb30e139a58fed0fa54
+
+COUNT = 213
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffc0000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 97e8adf65638fd9cdf3bc22c17fe4dbd
+
+COUNT = 214
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1ee6ee326583a0586491c96418d1a35d
+
+COUNT = 215
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 26b549c2ec756f82ecc48008e529956b
+
+COUNT = 216
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffff8000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 70377b6da669b072129e057cc28e9ca5
+
+COUNT = 217
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffc000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9c94b8b0cb8bcc919072262b3fa05ad9
+
+COUNT = 218
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2fbb83dfd0d7abcb05cd28cad2dfb523
+
+COUNT = 219
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 96877803de77744bb970d0a91f4debae
+
+COUNT = 220
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffff800000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7379f3370cf6e5ce12ae5969c8eea312
+
+COUNT = 221
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 02dc99fa3d4f98ce80985e7233889313
+
+COUNT = 222
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1e38e759075ba5cab6457da51844295a
+
+COUNT = 223
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 70bed8dbf615868a1f9d9b05d3e7a267
+
+COUNT = 224
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 234b148b8cb1d8c32b287e896903d150
+
+COUNT = 225
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 294b033df4da853f4be3e243f7e513f4
+
+COUNT = 226
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3f58c950f0367160adec45f2441e7411
+
+COUNT = 227
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 37f655536a704e5ace182d742a820cf4
+
+COUNT = 228
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ea7bd6bb63418731aeac790fe42d61e8
+
+COUNT = 229
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffc000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e74a4c999b4c064e48bb1e413f51e5ea
+
+COUNT = 230
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ba9ebefdb4ccf30f296cecb3bc1943e8
+
+COUNT = 231
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3194367a4898c502c13bb7478640a72d
+
+COUNT = 232
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = da797713263d6f33a5478a65ef60d412
+
+COUNT = 233
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d1ac39bb1ef86b9c1344f214679aa376
+
+COUNT = 234
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2fdea9e650532be5bc0e7325337fd363
+
+COUNT = 235
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d3a204dbd9c2af158b6ca67a5156ce4a
+
+COUNT = 236
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3a0a0e75a8da36735aee6684d965a778
+
+COUNT = 237
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 52fc3e620492ea99641ea168da5b6d52
+
+COUNT = 238
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d2e0c7f15b4772467d2cfc873000b2ca
+
+COUNT = 239
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 563531135e0c4d70a38f8bdb190ba04e
+
+COUNT = 240
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a8a39a0f5663f4c0fe5f2d3cafff421a
+
+COUNT = 241
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d94b5e90db354c1e42f61fabe167b2c0
+
+COUNT = 242
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 50e6d3c9b6698a7cd276f96b1473f35a
+
+COUNT = 243
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9338f08e0ebee96905d8f2e825208f43
+
+COUNT = 244
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8b378c86672aa54a3a266ba19d2580ca
+
+COUNT = 245
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cca7c3086f5f9511b31233da7cab9160
+
+COUNT = 246
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5b40ff4ec9be536ba23035fa4f06064c
+
+COUNT = 247
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 60eb5af8416b257149372194e8b88749
+
+COUNT = 248
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2f005a8aed8a361c92e440c15520cbd1
+
+COUNT = 249
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7b03627611678a997717578807a800e2
+
+COUNT = 250
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cf78618f74f6f3696e0a4779b90b5a77
+
+COUNT = 251
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 03720371a04962eaea0a852e69972858
+
+COUNT = 252
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1f8a8133aa8ccf70e2bd3285831ca6b7
+
+COUNT = 253
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 27936bd27fb1468fc8b48bc483321725
+
+COUNT = 254
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b07d4f3e2cd2ef2eb545980754dfea0f
+
+COUNT = 255
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4bf85f1b5d54adbc307b0a048389adcb
+
--- /dev/null
+#include <AES.h>
+
+AES aes ;
+
+byte key [2*N_BLOCK] ;
+byte plain [N_BLOCK] ;
+byte iv [N_BLOCK] ;
+byte cipher [N_BLOCK] ;
+byte check [N_BLOCK] ;
+
+void loop ()
+{}
+
+
+void setup ()
+{
+ Serial.begin (57600) ;
+ Serial.print ("AES library test vectors") ;
+
+ monte_carlo (128) ;
+
+ for (int keysize = 128 ; keysize <= 256 ; keysize += 64)
+ {
+ prekey_test_var_plaintext (keysize) ;
+ prekey_test_var_key (keysize) ;
+ }
+}
+
+
+void prekey_test_var_plaintext (int bits)
+{
+ Serial.println () ;
+ Serial.print ("ECB Varying Plaintext ") ;
+ Serial.print (bits) ;
+ Serial.println (" bits") ;
+ Serial.println () ;
+
+ byte succ ;
+ set_bits (bits, key, 0) ; // all zero key
+ succ = aes.set_key (key, bits) ;
+ if (succ != SUCCESS)
+ Serial.println ("Failure set_key") ;
+
+
+ for (int bitcount = 1 ; bitcount <= 128 ; bitcount++)
+ {
+ Serial.print ("COUNT = ") ; Serial.println (bitcount-1) ;
+ print_value ("KEY = ", key, bits) ;
+ set_bits (128, plain, bitcount) ;
+
+ print_value ("PLAINTEXT = ", plain, 128) ;
+
+ succ = aes.encrypt (plain, cipher) ;
+ if (succ != SUCCESS)
+ Serial.println ("Failure encrypt") ;
+
+ print_value ("CIPHERTEXT = ", cipher, 128) ;
+
+ succ = aes.decrypt (cipher, check) ;
+ if (succ != SUCCESS)
+ Serial.println ("Failure decrypt") ;
+
+ //print_value ("CHECK = ", check, 128) ;
+ check_same (plain, check, 128) ;
+ Serial.println () ;
+ }
+}
+
+
+void prekey_test_var_key (int bits)
+{
+ Serial.println () ;
+ Serial.print ("ECB Varying Key ") ;
+ Serial.print (bits) ;
+ Serial.println (" bits") ;
+ Serial.println () ;
+
+ byte succ ;
+ set_bits (128, plain, 0) ;
+
+ for (int bitcount = 1 ; bitcount <= bits ; bitcount++)
+ {
+ set_bits (bits, key, bitcount) ; // all zero key
+ succ = aes.set_key (key, bits) ;
+ if (succ != SUCCESS)
+ Serial.println ("Failure set_key") ;
+ Serial.print ("COUNT = ") ; Serial.println (bitcount-1) ;
+ print_value ("KEY = ", key, bits) ;
+
+ print_value ("PLAINTEXT = ", plain, 128) ;
+
+ succ = aes.encrypt (plain, cipher) ;
+ if (succ != SUCCESS)
+ Serial.println ("Failure encrypt") ;
+
+ print_value ("CIPHERTEXT = ", cipher, 128) ;
+
+ succ = aes.decrypt (cipher, check) ;
+ if (succ != SUCCESS)
+ Serial.println ("Failure decrypt") ;
+
+ check_same (plain, check, 128) ;
+ Serial.println () ;
+ }
+}
+
+void set_bits (int bits, byte * a, int count)
+{
+ bits >>= 3 ;
+ byte bcount = count >> 3 ;
+ for (byte i = 0 ; i < bcount ; i++)
+ a [i] = 0xFF ;
+ if ((count & 7) != 0)
+ a [bcount++] = 0xFF & (0xFF00 >> (count & 7)) ;
+ for (byte i = bcount ; i < bits ; i++)
+ a [i] = 0x00 ;
+}
+
+void check_same (byte * a, byte * b, int bits)
+{
+ bits >>= 3 ;
+ for (byte i = 0 ; i < bits ; i++)
+ if (a[i] != b[i])
+ {
+ Serial.println ("Failure plain != check") ;
+ return ;
+ }
+}
+
+char hex[] = "0123456789abcdef" ;
+
+
+void print_value (const char * str, byte * a, int bits)
+{
+ Serial.print (str) ;
+ bits >>= 3 ;
+ for (int i = 0 ; i < bits ; i++)
+ {
+ byte b = a[i] ;
+ Serial.print (hex [b >> 4]) ;
+ Serial.print (hex [b & 15]) ;
+ }
+ Serial.println () ;
+}
+
+byte monteplain [] =
+ { 0xb9, 0x14, 0x5a, 0x76, 0x8b, 0x7d, 0xc4, 0x89,
+ 0xa0, 0x96, 0xb5, 0x46, 0xf4, 0x3b, 0x23, 0x1f } ;
+byte montekey [] =
+ { 0x13, 0x9a, 0x35, 0x42, 0x2f, 0x1d, 0x61, 0xde,
+ 0x3c, 0x91, 0x78, 0x7f, 0xe0, 0x50, 0x7a, 0xfd } ;
+
+void monte_carlo (int bits)
+{
+ Serial.println () ;
+ Serial.print ("Monte Carlo ") ;
+ Serial.print (bits) ;
+ Serial.println (" bits") ;
+ Serial.println () ;
+ byte succ ;
+ for (int i = 0 ; i < 16 ; i++)
+ {
+ plain [i] = monteplain [i] ;
+ key [i] = montekey [i] ;
+ }
+ for (int i = 0 ; i < 100 ; i++)
+ {
+ Serial.print ("COUNT = ") ; Serial.println (i) ;
+ print_value ("KEY = ", key, bits) ;
+ print_value ("PLAINTEXT = ", plain, 128) ;
+ succ = aes.set_key (key, bits) ;
+ for (int j = 0 ; j < 1000 ; j++)
+ {
+ succ = aes.encrypt (plain, cipher) ;
+ aes.copy_n_bytes (plain, cipher, 16) ;
+ }
+ print_value ("CIPHERTEXT = ", cipher, 128) ;
+ Serial.println () ;
+ if (bits == 128)
+ {
+ for (byte k = 0 ; k < 16 ; k++)
+ key [k] ^= cipher [k] ;
+ }
+ else if (bits == 192)
+ {
+ }
+ else
+ {
+ }
+ }
+}
--- /dev/null
+#############################################################################
+#
+# Makefile for AES examples on Raspberry Pi
+#
+# License: GPL (General Public License)
+# Author: gnulnulf <arco@appeltaart.mine.nu>
+# Date: 2013/02/07 (version 1.0)
+#
+# Description:
+# ------------
+# use make all and make install to install the examples
+# You can change the install directory by editing the prefix line
+#
+prefix := /usr/local
+
+# The recommended compiler flags for the Raspberry Pi
+CCFLAGS=-Ofast -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s
+#CCFLAGS=
+
+# define all programs
+PROGRAMS = aes test_vectors
+SOURCES = ${PROGRAMS:=.cpp}
+
+all: ${PROGRAMS}
+
+${PROGRAMS}: ${SOURCES}
+ g++ ${CCFLAGS} -Wall -I../ -lAES $@.cpp -o $@
+
+clean:
+ rm -rf $(PROGRAMS)
+
+install: all
+ test -d $(prefix) || mkdir $(prefix)
+ test -d $(prefix)/bin || mkdir $(prefix)/bin
+ for prog in $(PROGRAMS); do \
+ install -m 0755 $$prog $(prefix)/bin; \
+ done
+
+.PHONY: install
--- /dev/null
+Monte Carlo test vectors:
+ http://csrc.nist.gov/groups/STM/cavp/documents/aes/aesmct.zip
+
+(Compare the Monte Carlo output to the ECBMCT128.rsp file)
+
+Known Answer Tests:
+ http://csrc.nist.gov/groups/STM/cavp/documents/aes/KAT_AES.zip
+
+- Compare the other test outputs to
+ ECBVarTxt128.rsp
+ ECBVarKey128.rsp
+ ECBVarTxt192.rsp
+ ECBVarKey192.rsp
+ ECBVarTxt256.rsp
+ ECBVarKey256.rsp
+
--- /dev/null
+#include <AES.h>
+#include "printf.h"
+
+AES aes;
+
+void prekey_test ();
+void prekey (int bits, int blocks);
+
+byte key[] = "01234567899876543210012345678998";
+
+byte plain[] = "TESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTEST";
+
+//real iv = iv x2 ex: 01234567 = 0123456701234567
+unsigned long long int my_iv = 01234567;
+
+int main(int argc, char** argv)
+{
+ printf("\n===testng mode\n") ;
+
+ for (int i=0;i<1;i++){
+ prekey_test () ;
+ }
+}
+
+void prekey (int bits)
+{
+ byte iv [N_BLOCK] ;
+ byte plain_p[sizeof(plain) + (N_BLOCK - (sizeof(plain) % 16)) - 1];
+ byte cipher[sizeof(plain_p)];
+ aes.do_aes_encrypt(plain,sizeof(plain),cipher,key,bits);
+ aes.get_IV(iv);
+ aes.do_aes_decrypt(cipher,aes.get_size(),plain_p,key,bits,iv);
+ //normally u have sizeof(cipher) but if its in the same sketch you cannot determin it dynamically
+
+ printf("\n\nPLAIN :");
+ aes.printArray(plain);
+ printf("\nCIPHER:");
+ aes.printArray(cipher);
+ printf("\nPlain2:");
+ aes.printArray(plain_p);
+ printf("\n============================================================\n");
+}
+
+void prekey_test ()
+{
+ prekey (128) ;
+}
--- /dev/null
+AES library test vectors
+Monte Carlo 128 bits
+
+COUNT = 0
+KEY = 139a35422f1d61de3c91787fe0507afd
+PLAINTEXT = b9145a768b7dc489a096b546f43b231f
+CIPHERTEXT = d7c3ffac9031238650901e157364c386
+
+COUNT = 1
+KEY = c459caeebf2c42586c01666a9334b97b
+PLAINTEXT = d7c3ffac9031238650901e157364c386
+CIPHERTEXT = bc3637da2daf8fcf7c68bb28c143a0a4
+
+COUNT = 2
+KEY = 786ffd349283cd971069dd42527719df
+PLAINTEXT = bc3637da2daf8fcf7c68bb28c143a0a4
+CIPHERTEXT = 9c88a8db798f48df1ac4936afa959eac
+
+COUNT = 3
+KEY = e4e755efeb0c85480aad4e28a8e28773
+PLAINTEXT = 9c88a8db798f48df1ac4936afa959eac
+CIPHERTEXT = b87aaa1c76a775d94c2ddf82abe5c66e
+
+COUNT = 4
+KEY = 5c9dfff39dabf091468091aa0307411d
+PLAINTEXT = b87aaa1c76a775d94c2ddf82abe5c66e
+CIPHERTEXT = 79ee212734f14d1bf5a59d46e8c2fa34
+
+COUNT = 5
+KEY = 2573ded4a95abd8ab3250cecebc5bb29
+PLAINTEXT = 79ee212734f14d1bf5a59d46e8c2fa34
+CIPHERTEXT = 09df49135aeb8e373a19fa457ab280a0
+
+COUNT = 6
+KEY = 2cac97c7f3b133bd893cf6a991773b89
+PLAINTEXT = 09df49135aeb8e373a19fa457ab280a0
+CIPHERTEXT = c52263efa6379209d17e87ac250615cb
+
+COUNT = 7
+KEY = e98ef4285586a1b458427105b4712e42
+PLAINTEXT = c52263efa6379209d17e87ac250615cb
+CIPHERTEXT = 336bed017e10a247ee92989862431163
+
+COUNT = 8
+KEY = dae519292b9603f3b6d0e99dd6323f21
+PLAINTEXT = 336bed017e10a247ee92989862431163
+CIPHERTEXT = b13310581ffe5b10aaefdeb8992aec18
+
+COUNT = 9
+KEY = 6bd60971346858e31c3f37254f18d339
+PLAINTEXT = b13310581ffe5b10aaefdeb8992aec18
+CIPHERTEXT = b0eaede3f3eebfef88822a6ede1950b1
+
+COUNT = 10
+KEY = db3ce492c786e70c94bd1d4b91018388
+PLAINTEXT = b0eaede3f3eebfef88822a6ede1950b1
+CIPHERTEXT = 37891fc253b00de13155d5517e1b7890
+
+COUNT = 11
+KEY = ecb5fb509436eaeda5e8c81aef1afb18
+PLAINTEXT = 37891fc253b00de13155d5517e1b7890
+CIPHERTEXT = 8f574c85fa44af2d43c95ee5f627fc9d
+
+COUNT = 12
+KEY = 63e2b7d56e7245c0e62196ff193d0785
+PLAINTEXT = 8f574c85fa44af2d43c95ee5f627fc9d
+CIPHERTEXT = 6c0af6709225f328a0225b2280efa3e3
+
+COUNT = 13
+KEY = 0fe841a5fc57b6e84603cddd99d2a466
+PLAINTEXT = 6c0af6709225f328a0225b2280efa3e3
+CIPHERTEXT = e2dc36073fe192e712373a8702e8adce
+
+COUNT = 14
+KEY = ed3477a2c3b6240f5434f75a9b3a09a8
+PLAINTEXT = e2dc36073fe192e712373a8702e8adce
+CIPHERTEXT = 1e91d1e1f82f1d320186210a792f7ba1
+
+COUNT = 15
+KEY = f3a5a6433b99393d55b2d650e2157209
+PLAINTEXT = 1e91d1e1f82f1d320186210a792f7ba1
+CIPHERTEXT = 228eac74166da261d7fa83f43d9ddd2f
+
+COUNT = 16
+KEY = d12b0a372df49b5c824855a4df88af26
+PLAINTEXT = 228eac74166da261d7fa83f43d9ddd2f
+CIPHERTEXT = 25d0de6a894361a1b83d5fa2fd607f26
+
+COUNT = 17
+KEY = f4fbd45da4b7fafd3a750a0622e8d000
+PLAINTEXT = 25d0de6a894361a1b83d5fa2fd607f26
+CIPHERTEXT = 36095dc3e659ec50ca7f6f8207d20031
+
+COUNT = 18
+KEY = c2f2899e42ee16adf00a6584253ad031
+PLAINTEXT = 36095dc3e659ec50ca7f6f8207d20031
+CIPHERTEXT = 8dbfe965078468875d86145164c4ab4f
+
+COUNT = 19
+KEY = 4f4d60fb456a7e2aad8c71d541fe7b7e
+PLAINTEXT = 8dbfe965078468875d86145164c4ab4f
+CIPHERTEXT = 4032bb8137d4b9eb93644359a995bb4e
+
+COUNT = 20
+KEY = 0f7fdb7a72bec7c13ee8328ce86bc030
+PLAINTEXT = 4032bb8137d4b9eb93644359a995bb4e
+CIPHERTEXT = 85308aa92c625a25bd5f4a40375c6baa
+
+COUNT = 21
+KEY = 8a4f51d35edc9de483b778ccdf37ab9a
+PLAINTEXT = 85308aa92c625a25bd5f4a40375c6baa
+CIPHERTEXT = 73283fc59e04e80a867e478d97a3f388
+
+COUNT = 22
+KEY = f9676e16c0d875ee05c93f4148945812
+PLAINTEXT = 73283fc59e04e80a867e478d97a3f388
+CIPHERTEXT = 418c1fe377e4ef9832f20286b167f916
+
+COUNT = 23
+KEY = b8eb71f5b73c9a76373b3dc7f9f3a104
+PLAINTEXT = 418c1fe377e4ef9832f20286b167f916
+CIPHERTEXT = 60ad1341525e67cffdd68ff671253c77
+
+COUNT = 24
+KEY = d84662b4e562fdb9caedb23188d69d73
+PLAINTEXT = 60ad1341525e67cffdd68ff671253c77
+CIPHERTEXT = 4edf6e01a76de6153d17713a49d5b028
+
+COUNT = 25
+KEY = 96990cb5420f1bacf7fac30bc1032d5b
+PLAINTEXT = 4edf6e01a76de6153d17713a49d5b028
+CIPHERTEXT = 2c85ebf9e3d80596f78712df56ac77cd
+
+COUNT = 26
+KEY = ba1ce74ca1d71e3a007dd1d497af5a96
+PLAINTEXT = 2c85ebf9e3d80596f78712df56ac77cd
+CIPHERTEXT = 8fc8ef9ab7462712977e87c741795ece
+
+COUNT = 27
+KEY = 35d408d61691392897035613d6d60458
+PLAINTEXT = 8fc8ef9ab7462712977e87c741795ece
+CIPHERTEXT = 37e9ac800cfb19133b4e9b0c418ca098
+
+COUNT = 28
+KEY = 023da4561a6a203bac4dcd1f975aa4c0
+PLAINTEXT = 37e9ac800cfb19133b4e9b0c418ca098
+CIPHERTEXT = cb7cd7619caa605e45f95f5b31a85495
+
+COUNT = 29
+KEY = c941733786c04065e9b49244a6f2f055
+PLAINTEXT = cb7cd7619caa605e45f95f5b31a85495
+CIPHERTEXT = 6e265e5fd030847b8841bf6652996392
+
+COUNT = 30
+KEY = a7672d6856f0c41e61f52d22f46b93c7
+PLAINTEXT = 6e265e5fd030847b8841bf6652996392
+CIPHERTEXT = 5c9a7d2ce1c86f0b3425b3b6aae108e0
+
+COUNT = 31
+KEY = fbfd5044b738ab1555d09e945e8a9b27
+PLAINTEXT = 5c9a7d2ce1c86f0b3425b3b6aae108e0
+CIPHERTEXT = c911dee5ff318a7e799f92daadcb3d9a
+
+COUNT = 32
+KEY = 32ec8ea14809216b2c4f0c4ef341a6bd
+PLAINTEXT = c911dee5ff318a7e799f92daadcb3d9a
+CIPHERTEXT = 7a3afdf10410f1c47c7d928d4a8d432a
+
+COUNT = 33
+KEY = 48d673504c19d0af50329ec3b9cce597
+PLAINTEXT = 7a3afdf10410f1c47c7d928d4a8d432a
+CIPHERTEXT = c681b7b6d3ec9dc91012e3b7427c67ad
+
+COUNT = 34
+KEY = 8e57c4e69ff54d6640207d74fbb0823a
+PLAINTEXT = c681b7b6d3ec9dc91012e3b7427c67ad
+CIPHERTEXT = cd3f84bbe958536d502065eb37ae10b4
+
+COUNT = 35
+KEY = 4368405d76ad1e0b1000189fcc1e928e
+PLAINTEXT = cd3f84bbe958536d502065eb37ae10b4
+CIPHERTEXT = 879db797e686b9116c25c07f4ae67593
+
+COUNT = 36
+KEY = c4f5f7ca902ba71a7c25d8e086f8e71d
+PLAINTEXT = 879db797e686b9116c25c07f4ae67593
+CIPHERTEXT = 5959ebd7a1167713429eda69538c536b
+
+COUNT = 37
+KEY = 9dac1c1d313dd0093ebb0289d574b476
+PLAINTEXT = 5959ebd7a1167713429eda69538c536b
+CIPHERTEXT = f57101d7fa19f97a31d60b276312717c
+
+COUNT = 38
+KEY = 68dd1dcacb2429730f6d09aeb666c50a
+PLAINTEXT = f57101d7fa19f97a31d60b276312717c
+CIPHERTEXT = 6dfbbc2b147568c55adbfdc3c706edb0
+
+COUNT = 39
+KEY = 0526a1e1df5141b655b6f46d716028ba
+PLAINTEXT = 6dfbbc2b147568c55adbfdc3c706edb0
+CIPHERTEXT = 9c4ea9002306d75e7b0f03e2a72b7a1d
+
+COUNT = 40
+KEY = 996808e1fc5796e82eb9f78fd64b52a7
+PLAINTEXT = 9c4ea9002306d75e7b0f03e2a72b7a1d
+CIPHERTEXT = cb9975336cc05f0114f26bde4cc84f8d
+
+COUNT = 41
+KEY = 52f17dd29097c9e93a4b9c519a831d2a
+PLAINTEXT = cb9975336cc05f0114f26bde4cc84f8d
+CIPHERTEXT = 902c4250cff110d792938e8dcd534cf0
+
+COUNT = 42
+KEY = c2dd3f825f66d93ea8d812dc57d051da
+PLAINTEXT = 902c4250cff110d792938e8dcd534cf0
+CIPHERTEXT = 140242f195ef2ef7f6ee23574c071311
+
+COUNT = 43
+KEY = d6df7d73ca89f7c95e36318b1bd742cb
+PLAINTEXT = 140242f195ef2ef7f6ee23574c071311
+CIPHERTEXT = 3c6d4ffafde866f1e994480c47d20a04
+
+COUNT = 44
+KEY = eab2328937619138b7a279875c0548cf
+PLAINTEXT = 3c6d4ffafde866f1e994480c47d20a04
+CIPHERTEXT = 1ca04a21addc38ef8bfc8989d3d6b33b
+
+COUNT = 45
+KEY = f61278a89abda9d73c5ef00e8fd3fbf4
+PLAINTEXT = 1ca04a21addc38ef8bfc8989d3d6b33b
+CIPHERTEXT = bb8875ee3c3c8c0987b1c20f999028e9
+
+COUNT = 46
+KEY = 4d9a0d46a68125debbef32011643d31d
+PLAINTEXT = bb8875ee3c3c8c0987b1c20f999028e9
+CIPHERTEXT = 9d33724d80a76f2033a37a851403ef28
+
+COUNT = 47
+KEY = d0a97f0b26264afe884c488402403c35
+PLAINTEXT = 9d33724d80a76f2033a37a851403ef28
+CIPHERTEXT = 4c92fe152d16da8ea59b9f29c75f20ff
+
+COUNT = 48
+KEY = 9c3b811e0b3090702dd7d7adc51f1cca
+PLAINTEXT = 4c92fe152d16da8ea59b9f29c75f20ff
+CIPHERTEXT = 659c76f73032b0192b281034b6a99a3f
+
+COUNT = 49
+KEY = f9a7f7e93b02206906ffc79973b686f5
+PLAINTEXT = 659c76f73032b0192b281034b6a99a3f
+CIPHERTEXT = 5d296637697ccad84fc77936a31c2655
+
+COUNT = 50
+KEY = a48e91de527eeab14938beafd0aaa0a0
+PLAINTEXT = 5d296637697ccad84fc77936a31c2655
+CIPHERTEXT = a72a596a030d5541bc4d0fc739491d5b
+
+COUNT = 51
+KEY = 03a4c8b45173bff0f575b168e9e3bdfb
+PLAINTEXT = a72a596a030d5541bc4d0fc739491d5b
+CIPHERTEXT = 5f5ec53c91225717fcba470688dfa364
+
+COUNT = 52
+KEY = 5cfa0d88c051e8e709cff66e613c1e9f
+PLAINTEXT = 5f5ec53c91225717fcba470688dfa364
+CIPHERTEXT = 5719cb14eba820c0d51109a0c7a4154f
+
+COUNT = 53
+KEY = 0be3c69c2bf9c827dcdeffcea6980bd0
+PLAINTEXT = 5719cb14eba820c0d51109a0c7a4154f
+CIPHERTEXT = 3abd186712a9def73b6312b5300f02af
+
+COUNT = 54
+KEY = 315edefb395016d0e7bded7b9697097f
+PLAINTEXT = 3abd186712a9def73b6312b5300f02af
+CIPHERTEXT = b1e90c8c0d4c9651a6de7f52a63ac456
+
+COUNT = 55
+KEY = 80b7d277341c80814163922930adcd29
+PLAINTEXT = b1e90c8c0d4c9651a6de7f52a63ac456
+CIPHERTEXT = 5d26e33aae1441554034c77bde451679
+
+COUNT = 56
+KEY = dd91314d9a08c1d401575552eee8db50
+PLAINTEXT = 5d26e33aae1441554034c77bde451679
+CIPHERTEXT = 93e44cdce14803544a53bc5b520c156f
+
+COUNT = 57
+KEY = 4e757d917b40c2804b04e909bce4ce3f
+PLAINTEXT = 93e44cdce14803544a53bc5b520c156f
+CIPHERTEXT = 8ee3b6fd953b441043f69f3747e4cf63
+
+COUNT = 58
+KEY = c096cb6cee7b869008f2763efb00015c
+PLAINTEXT = 8ee3b6fd953b441043f69f3747e4cf63
+CIPHERTEXT = cb2f545970200630e5145f817a013807
+
+COUNT = 59
+KEY = 0bb99f359e5b80a0ede629bf8101395b
+PLAINTEXT = cb2f545970200630e5145f817a013807
+CIPHERTEXT = 50047276451ce19cb14d8d2ef0b3851b
+
+COUNT = 60
+KEY = 5bbded43db47613c5caba49171b2bc40
+PLAINTEXT = 50047276451ce19cb14d8d2ef0b3851b
+CIPHERTEXT = d243791dde33c2a4333ef4dcbcadbd3a
+
+COUNT = 61
+KEY = 89fe945e0574a3986f95504dcd1f017a
+PLAINTEXT = d243791dde33c2a4333ef4dcbcadbd3a
+CIPHERTEXT = 343181860092a5e33c2e1c441a9f6804
+
+COUNT = 62
+KEY = bdcf15d805e6067b53bb4c09d780697e
+PLAINTEXT = 343181860092a5e33c2e1c441a9f6804
+CIPHERTEXT = 4e7cdd553d732909e25a13a521e04078
+
+COUNT = 63
+KEY = f3b3c88d38952f72b1e15facf6602906
+PLAINTEXT = 4e7cdd553d732909e25a13a521e04078
+CIPHERTEXT = 9c16f3fda49bb6a2b6d76a6696bd768f
+
+COUNT = 64
+KEY = 6fa53b709c0e99d0073635ca60dd5f89
+PLAINTEXT = 9c16f3fda49bb6a2b6d76a6696bd768f
+CIPHERTEXT = 9eb63f9099123591a4ca7aa0fff55a49
+
+COUNT = 65
+KEY = f11304e0051cac41a3fc4f6a9f2805c0
+PLAINTEXT = 9eb63f9099123591a4ca7aa0fff55a49
+CIPHERTEXT = aa6a9e40aad692550b7c87b92b205af0
+
+COUNT = 66
+KEY = 5b799aa0afca3e14a880c8d3b4085f30
+PLAINTEXT = aa6a9e40aad692550b7c87b92b205af0
+CIPHERTEXT = ae92c267f38b9b4623df36523bb739b6
+
+COUNT = 67
+KEY = f5eb58c75c41a5528b5ffe818fbf6686
+PLAINTEXT = ae92c267f38b9b4623df36523bb739b6
+CIPHERTEXT = 39c0de843767dfa2d563c0632405d595
+
+COUNT = 68
+KEY = cc2b86436b267af05e3c3ee2abbab313
+PLAINTEXT = 39c0de843767dfa2d563c0632405d595
+CIPHERTEXT = 80a9445be75373b07476608feb1f1c7b
+
+COUNT = 69
+KEY = 4c82c2188c7509402a4a5e6d40a5af68
+PLAINTEXT = 80a9445be75373b07476608feb1f1c7b
+CIPHERTEXT = 5306f5a77e42d9f4cee8f134ba1448c6
+
+COUNT = 70
+KEY = 1f8437bff237d0b4e4a2af59fab1e7ae
+PLAINTEXT = 5306f5a77e42d9f4cee8f134ba1448c6
+CIPHERTEXT = 8db0c3fba7dc797cd175d97503759260
+
+COUNT = 71
+KEY = 9234f44455eba9c835d7762cf9c475ce
+PLAINTEXT = 8db0c3fba7dc797cd175d97503759260
+CIPHERTEXT = 04fcb0c77ae0c98d2afb178ab2c2b02d
+
+COUNT = 72
+KEY = 96c844832f0b60451f2c61a64b06c5e3
+PLAINTEXT = 04fcb0c77ae0c98d2afb178ab2c2b02d
+CIPHERTEXT = 1a156581b3557078971cc6877a3d9339
+
+COUNT = 73
+KEY = 8cdd21029c5e103d8830a721313b56da
+PLAINTEXT = 1a156581b3557078971cc6877a3d9339
+CIPHERTEXT = e47087289290fa2b6734eeaab2fc815d
+
+COUNT = 74
+KEY = 68ada62a0eceea16ef04498b83c7d787
+PLAINTEXT = e47087289290fa2b6734eeaab2fc815d
+CIPHERTEXT = 00ce641525020d35244e2227287b2a20
+
+COUNT = 75
+KEY = 6863c23f2bcce723cb4a6bacabbcfda7
+PLAINTEXT = 00ce641525020d35244e2227287b2a20
+CIPHERTEXT = ecf623cef1e420d0994070c078592c97
+
+COUNT = 76
+KEY = 8495e1f1da28c7f3520a1b6cd3e5d130
+PLAINTEXT = ecf623cef1e420d0994070c078592c97
+CIPHERTEXT = 256c8f28df4a286fb05514fcfa8cbcaf
+
+COUNT = 77
+KEY = a1f96ed90562ef9ce25f0f9029696d9f
+PLAINTEXT = 256c8f28df4a286fb05514fcfa8cbcaf
+CIPHERTEXT = fd4aed4b5a2b8edefe3cc2aef6ecd298
+
+COUNT = 78
+KEY = 5cb383925f4961421c63cd3edf85bf07
+PLAINTEXT = fd4aed4b5a2b8edefe3cc2aef6ecd298
+CIPHERTEXT = dfe0e571f77f0b46c52f003e774918ac
+
+COUNT = 79
+KEY = 835366e3a8366a04d94ccd00a8cca7ab
+PLAINTEXT = dfe0e571f77f0b46c52f003e774918ac
+CIPHERTEXT = e421fbeb4c23745b97578162f89e68fc
+
+COUNT = 80
+KEY = 67729d08e4151e5f4e1b4c625052cf57
+PLAINTEXT = e421fbeb4c23745b97578162f89e68fc
+CIPHERTEXT = c38c0bbde031d1a79438f79ff7cc68a5
+
+COUNT = 81
+KEY = a4fe96b50424cff8da23bbfda79ea7f2
+PLAINTEXT = c38c0bbde031d1a79438f79ff7cc68a5
+CIPHERTEXT = 86113133968aa3052709875bf033d804
+
+COUNT = 82
+KEY = 22efa78692ae6cfdfd2a3ca657ad7ff6
+PLAINTEXT = 86113133968aa3052709875bf033d804
+CIPHERTEXT = fd706bef1bf30c8d1e95543b75629e02
+
+COUNT = 83
+KEY = df9fcc69895d6070e3bf689d22cfe1f4
+PLAINTEXT = fd706bef1bf30c8d1e95543b75629e02
+CIPHERTEXT = 9a5bbb6125152f1352b10e1c1a172aa6
+
+COUNT = 84
+KEY = 45c47708ac484f63b10e668138d8cb52
+PLAINTEXT = 9a5bbb6125152f1352b10e1c1a172aa6
+CIPHERTEXT = 3ee69736488c51fa72784aa263618f45
+
+COUNT = 85
+KEY = 7b22e03ee4c41e99c3762c235bb94417
+PLAINTEXT = 3ee69736488c51fa72784aa263618f45
+CIPHERTEXT = fc66daa246ebcc320c7c89b599014633
+
+COUNT = 86
+KEY = 87443a9ca22fd2abcf0aa596c2b80224
+PLAINTEXT = fc66daa246ebcc320c7c89b599014633
+CIPHERTEXT = 35645885ed205d67e5caeff26646c38c
+
+COUNT = 87
+KEY = b22062194f0f8fcc2ac04a64a4fec1a8
+PLAINTEXT = 35645885ed205d67e5caeff26646c38c
+CIPHERTEXT = daeaa866aa4eacdb752caccb2c0ae6c1
+
+COUNT = 88
+KEY = 68caca7fe54123175fece6af88f42769
+PLAINTEXT = daeaa866aa4eacdb752caccb2c0ae6c1
+CIPHERTEXT = 29e88b1ae615fcd06b09e767459d6089
+
+COUNT = 89
+KEY = 412241650354dfc734e501c8cd6947e0
+PLAINTEXT = 29e88b1ae615fcd06b09e767459d6089
+CIPHERTEXT = 63470bff052e7f5c7a735cc2e6eb61ac
+
+COUNT = 90
+KEY = 22654a9a067aa09b4e965d0a2b82264c
+PLAINTEXT = 63470bff052e7f5c7a735cc2e6eb61ac
+CIPHERTEXT = f4fa6a3549cd2b33af9cac134d7b1402
+
+COUNT = 91
+KEY = d69f20af4fb78ba8e10af11966f9324e
+PLAINTEXT = f4fa6a3549cd2b33af9cac134d7b1402
+CIPHERTEXT = 5b22a82ccbae9b9c75f797e74e6da53d
+
+COUNT = 92
+KEY = 8dbd88838419103494fd66fe28949773
+PLAINTEXT = 5b22a82ccbae9b9c75f797e74e6da53d
+CIPHERTEXT = 87b51692f8f28743bd8dc843276f351a
+
+COUNT = 93
+KEY = 0a089e117ceb97772970aebd0ffba269
+PLAINTEXT = 87b51692f8f28743bd8dc843276f351a
+CIPHERTEXT = 150fb2180704a7623a1fab8bf17fba18
+
+COUNT = 94
+KEY = 1f072c097bef3015136f0536fe841871
+PLAINTEXT = 150fb2180704a7623a1fab8bf17fba18
+CIPHERTEXT = 8088874e7f3f09a98fd3f0a59f2a0b4b
+
+COUNT = 95
+KEY = 9f8fab4704d039bc9cbcf59361ae133a
+PLAINTEXT = 8088874e7f3f09a98fd3f0a59f2a0b4b
+CIPHERTEXT = 08e02c091057d81c05d917ea5c07cdd0
+
+COUNT = 96
+KEY = 976f874e1487e1a09965e2793da9deea
+PLAINTEXT = 08e02c091057d81c05d917ea5c07cdd0
+CIPHERTEXT = b9636b3e2752694c3685872fd0a9a0ea
+
+COUNT = 97
+KEY = 2e0cec7033d588ecafe06556ed007e00
+PLAINTEXT = b9636b3e2752694c3685872fd0a9a0ea
+CIPHERTEXT = 2610dae2b64d74a8cbb4f43fa2d0a603
+
+COUNT = 98
+KEY = 081c36928598fc44645491694fd0d803
+PLAINTEXT = 2610dae2b64d74a8cbb4f43fa2d0a603
+CIPHERTEXT = 9cc994eda697fb5545eaa502b2a30fd3
+
+COUNT = 99
+KEY = 94d5a27f230f071121be346bfd73d7d0
+PLAINTEXT = 9cc994eda697fb5545eaa502b2a30fd3
+CIPHERTEXT = fb2649694783b551eacd9d5db6126d47
+
+
+ECB Varying Plaintext 128 bits
+
+COUNT = 0
+KEY = 00000000000000000000000000000000
+PLAINTEXT = 80000000000000000000000000000000
+CIPHERTEXT = 3ad78e726c1ec02b7ebfe92b23d9ec34
+
+COUNT = 1
+KEY = 00000000000000000000000000000000
+PLAINTEXT = c0000000000000000000000000000000
+CIPHERTEXT = aae5939c8efdf2f04e60b9fe7117b2c2
+
+COUNT = 2
+KEY = 00000000000000000000000000000000
+PLAINTEXT = e0000000000000000000000000000000
+CIPHERTEXT = f031d4d74f5dcbf39daaf8ca3af6e527
+
+COUNT = 3
+KEY = 00000000000000000000000000000000
+PLAINTEXT = f0000000000000000000000000000000
+CIPHERTEXT = 96d9fd5cc4f07441727df0f33e401a36
+
+COUNT = 4
+KEY = 00000000000000000000000000000000
+PLAINTEXT = f8000000000000000000000000000000
+CIPHERTEXT = 30ccdb044646d7e1f3ccea3dca08b8c0
+
+COUNT = 5
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fc000000000000000000000000000000
+CIPHERTEXT = 16ae4ce5042a67ee8e177b7c587ecc82
+
+COUNT = 6
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fe000000000000000000000000000000
+CIPHERTEXT = b6da0bb11a23855d9c5cb1b4c6412e0a
+
+COUNT = 7
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ff000000000000000000000000000000
+CIPHERTEXT = db4f1aa530967d6732ce4715eb0ee24b
+
+COUNT = 8
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ff800000000000000000000000000000
+CIPHERTEXT = a81738252621dd180a34f3455b4baa2f
+
+COUNT = 9
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffc00000000000000000000000000000
+CIPHERTEXT = 77e2b508db7fd89234caf7939ee5621a
+
+COUNT = 10
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffe00000000000000000000000000000
+CIPHERTEXT = b8499c251f8442ee13f0933b688fcd19
+
+COUNT = 11
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fff00000000000000000000000000000
+CIPHERTEXT = 965135f8a81f25c9d630b17502f68e53
+
+COUNT = 12
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fff80000000000000000000000000000
+CIPHERTEXT = 8b87145a01ad1c6cede995ea3670454f
+
+COUNT = 13
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffc0000000000000000000000000000
+CIPHERTEXT = 8eae3b10a0c8ca6d1d3b0fa61e56b0b2
+
+COUNT = 14
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffe0000000000000000000000000000
+CIPHERTEXT = 64b4d629810fda6bafdf08f3b0d8d2c5
+
+COUNT = 15
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffff0000000000000000000000000000
+CIPHERTEXT = d7e5dbd3324595f8fdc7d7c571da6c2a
+
+COUNT = 16
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffff8000000000000000000000000000
+CIPHERTEXT = f3f72375264e167fca9de2c1527d9606
+
+COUNT = 17
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffc000000000000000000000000000
+CIPHERTEXT = 8ee79dd4f401ff9b7ea945d86666c13b
+
+COUNT = 18
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffe000000000000000000000000000
+CIPHERTEXT = dd35cea2799940b40db3f819cb94c08b
+
+COUNT = 19
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffff000000000000000000000000000
+CIPHERTEXT = 6941cb6b3e08c2b7afa581ebdd607b87
+
+COUNT = 20
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffff800000000000000000000000000
+CIPHERTEXT = 2c20f439f6bb097b29b8bd6d99aad799
+
+COUNT = 21
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffc00000000000000000000000000
+CIPHERTEXT = 625d01f058e565f77ae86378bd2c49b3
+
+COUNT = 22
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffe00000000000000000000000000
+CIPHERTEXT = c0b5fd98190ef45fbb4301438d095950
+
+COUNT = 23
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffff00000000000000000000000000
+CIPHERTEXT = 13001ff5d99806efd25da34f56be854b
+
+COUNT = 24
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffff80000000000000000000000000
+CIPHERTEXT = 3b594c60f5c8277a5113677f94208d82
+
+COUNT = 25
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffc0000000000000000000000000
+CIPHERTEXT = e9c0fc1818e4aa46bd2e39d638f89e05
+
+COUNT = 26
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffe0000000000000000000000000
+CIPHERTEXT = f8023ee9c3fdc45a019b4e985c7e1a54
+
+COUNT = 27
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffff0000000000000000000000000
+CIPHERTEXT = 35f40182ab4662f3023baec1ee796b57
+
+COUNT = 28
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffff8000000000000000000000000
+CIPHERTEXT = 3aebbad7303649b4194a6945c6cc3694
+
+COUNT = 29
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffc000000000000000000000000
+CIPHERTEXT = a2124bea53ec2834279bed7f7eb0f938
+
+COUNT = 30
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffe000000000000000000000000
+CIPHERTEXT = b9fb4399fa4facc7309e14ec98360b0a
+
+COUNT = 31
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffff000000000000000000000000
+CIPHERTEXT = c26277437420c5d634f715aea81a9132
+
+COUNT = 32
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffff800000000000000000000000
+CIPHERTEXT = 171a0e1b2dd424f0e089af2c4c10f32f
+
+COUNT = 33
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffc00000000000000000000000
+CIPHERTEXT = 7cadbe402d1b208fe735edce00aee7ce
+
+COUNT = 34
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffe00000000000000000000000
+CIPHERTEXT = 43b02ff929a1485af6f5c6d6558baa0f
+
+COUNT = 35
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffff00000000000000000000000
+CIPHERTEXT = 092faacc9bf43508bf8fa8613ca75dea
+
+COUNT = 36
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffff80000000000000000000000
+CIPHERTEXT = cb2bf8280f3f9742c7ed513fe802629c
+
+COUNT = 37
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffc0000000000000000000000
+CIPHERTEXT = 215a41ee442fa992a6e323986ded3f68
+
+COUNT = 38
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffe0000000000000000000000
+CIPHERTEXT = f21e99cf4f0f77cea836e11a2fe75fb1
+
+COUNT = 39
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffff0000000000000000000000
+CIPHERTEXT = 95e3a0ca9079e646331df8b4e70d2cd6
+
+COUNT = 40
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffff8000000000000000000000
+CIPHERTEXT = 4afe7f120ce7613f74fc12a01a828073
+
+COUNT = 41
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffc000000000000000000000
+CIPHERTEXT = 827f000e75e2c8b9d479beed913fe678
+
+COUNT = 42
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffe000000000000000000000
+CIPHERTEXT = 35830c8e7aaefe2d30310ef381cbf691
+
+COUNT = 43
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffff000000000000000000000
+CIPHERTEXT = 191aa0f2c8570144f38657ea4085ebe5
+
+COUNT = 44
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffff800000000000000000000
+CIPHERTEXT = 85062c2c909f15d9269b6c18ce99c4f0
+
+COUNT = 45
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffc00000000000000000000
+CIPHERTEXT = 678034dc9e41b5a560ed239eeab1bc78
+
+COUNT = 46
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffe00000000000000000000
+CIPHERTEXT = c2f93a4ce5ab6d5d56f1b93cf19911c1
+
+COUNT = 47
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffff00000000000000000000
+CIPHERTEXT = 1c3112bcb0c1dcc749d799743691bf82
+
+COUNT = 48
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffff80000000000000000000
+CIPHERTEXT = 00c55bd75c7f9c881989d3ec1911c0d4
+
+COUNT = 49
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffc0000000000000000000
+CIPHERTEXT = ea2e6b5ef182b7dff3629abd6a12045f
+
+COUNT = 50
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffe0000000000000000000
+CIPHERTEXT = 22322327e01780b17397f24087f8cc6f
+
+COUNT = 51
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffff0000000000000000000
+CIPHERTEXT = c9cacb5cd11692c373b2411768149ee7
+
+COUNT = 52
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffff8000000000000000000
+CIPHERTEXT = a18e3dbbca577860dab6b80da3139256
+
+COUNT = 53
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffc000000000000000000
+CIPHERTEXT = 79b61c37bf328ecca8d743265a3d425c
+
+COUNT = 54
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffe000000000000000000
+CIPHERTEXT = d2d99c6bcc1f06fda8e27e8ae3f1ccc7
+
+COUNT = 55
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffff000000000000000000
+CIPHERTEXT = 1bfd4b91c701fd6b61b7f997829d663b
+
+COUNT = 56
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffff800000000000000000
+CIPHERTEXT = 11005d52f25f16bdc9545a876a63490a
+
+COUNT = 57
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffc00000000000000000
+CIPHERTEXT = 3a4d354f02bb5a5e47d39666867f246a
+
+COUNT = 58
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffe00000000000000000
+CIPHERTEXT = d451b8d6e1e1a0ebb155fbbf6e7b7dc3
+
+COUNT = 59
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffff00000000000000000
+CIPHERTEXT = 6898d4f42fa7ba6a10ac05e87b9f2080
+
+COUNT = 60
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffff80000000000000000
+CIPHERTEXT = b611295e739ca7d9b50f8e4c0e754a3f
+
+COUNT = 61
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffc0000000000000000
+CIPHERTEXT = 7d33fc7d8abe3ca1936759f8f5deaf20
+
+COUNT = 62
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffe0000000000000000
+CIPHERTEXT = 3b5e0f566dc96c298f0c12637539b25c
+
+COUNT = 63
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffff0000000000000000
+CIPHERTEXT = f807c3e7985fe0f5a50e2cdb25c5109e
+
+COUNT = 64
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffff8000000000000000
+CIPHERTEXT = 41f992a856fb278b389a62f5d274d7e9
+
+COUNT = 65
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffc000000000000000
+CIPHERTEXT = 10d3ed7a6fe15ab4d91acbc7d0767ab1
+
+COUNT = 66
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffe000000000000000
+CIPHERTEXT = 21feecd45b2e675973ac33bf0c5424fc
+
+COUNT = 67
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffff000000000000000
+CIPHERTEXT = 1480cb3955ba62d09eea668f7c708817
+
+COUNT = 68
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffff800000000000000
+CIPHERTEXT = 66404033d6b72b609354d5496e7eb511
+
+COUNT = 69
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffc00000000000000
+CIPHERTEXT = 1c317a220a7d700da2b1e075b00266e1
+
+COUNT = 70
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffe00000000000000
+CIPHERTEXT = ab3b89542233f1271bf8fd0c0f403545
+
+COUNT = 71
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffff00000000000000
+CIPHERTEXT = d93eae966fac46dca927d6b114fa3f9e
+
+COUNT = 72
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffff80000000000000
+CIPHERTEXT = 1bdec521316503d9d5ee65df3ea94ddf
+
+COUNT = 73
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffc0000000000000
+CIPHERTEXT = eef456431dea8b4acf83bdae3717f75f
+
+COUNT = 74
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffe0000000000000
+CIPHERTEXT = 06f2519a2fafaa596bfef5cfa15c21b9
+
+COUNT = 75
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffff0000000000000
+CIPHERTEXT = 251a7eac7e2fe809e4aa8d0d7012531a
+
+COUNT = 76
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffff8000000000000
+CIPHERTEXT = 3bffc16e4c49b268a20f8d96a60b4058
+
+COUNT = 77
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffc000000000000
+CIPHERTEXT = e886f9281999c5bb3b3e8862e2f7c988
+
+COUNT = 78
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffe000000000000
+CIPHERTEXT = 563bf90d61beef39f48dd625fcef1361
+
+COUNT = 79
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffff000000000000
+CIPHERTEXT = 4d37c850644563c69fd0acd9a049325b
+
+COUNT = 80
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffff800000000000
+CIPHERTEXT = b87c921b91829ef3b13ca541ee1130a6
+
+COUNT = 81
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffc00000000000
+CIPHERTEXT = 2e65eb6b6ea383e109accce8326b0393
+
+COUNT = 82
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffe00000000000
+CIPHERTEXT = 9ca547f7439edc3e255c0f4d49aa8990
+
+COUNT = 83
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffff00000000000
+CIPHERTEXT = a5e652614c9300f37816b1f9fd0c87f9
+
+COUNT = 84
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffff80000000000
+CIPHERTEXT = 14954f0b4697776f44494fe458d814ed
+
+COUNT = 85
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffc0000000000
+CIPHERTEXT = 7c8d9ab6c2761723fe42f8bb506cbcf7
+
+COUNT = 86
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffe0000000000
+CIPHERTEXT = db7e1932679fdd99742aab04aa0d5a80
+
+COUNT = 87
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffff0000000000
+CIPHERTEXT = 4c6a1c83e568cd10f27c2d73ded19c28
+
+COUNT = 88
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffff8000000000
+CIPHERTEXT = 90ecbe6177e674c98de412413f7ac915
+
+COUNT = 89
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffc000000000
+CIPHERTEXT = 90684a2ac55fe1ec2b8ebd5622520b73
+
+COUNT = 90
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffe000000000
+CIPHERTEXT = 7472f9a7988607ca79707795991035e6
+
+COUNT = 91
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffff000000000
+CIPHERTEXT = 56aff089878bf3352f8df172a3ae47d8
+
+COUNT = 92
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffff800000000
+CIPHERTEXT = 65c0526cbe40161b8019a2a3171abd23
+
+COUNT = 93
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffc00000000
+CIPHERTEXT = 377be0be33b4e3e310b4aabda173f84f
+
+COUNT = 94
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffe00000000
+CIPHERTEXT = 9402e9aa6f69de6504da8d20c4fcaa2f
+
+COUNT = 95
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffff00000000
+CIPHERTEXT = 123c1f4af313ad8c2ce648b2e71fb6e1
+
+COUNT = 96
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffff80000000
+CIPHERTEXT = 1ffc626d30203dcdb0019fb80f726cf4
+
+COUNT = 97
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffc0000000
+CIPHERTEXT = 76da1fbe3a50728c50fd2e621b5ad885
+
+COUNT = 98
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffe0000000
+CIPHERTEXT = 082eb8be35f442fb52668e16a591d1d6
+
+COUNT = 99
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffff0000000
+CIPHERTEXT = e656f9ecf5fe27ec3e4a73d00c282fb3
+
+COUNT = 100
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffff8000000
+CIPHERTEXT = 2ca8209d63274cd9a29bb74bcd77683a
+
+COUNT = 101
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffc000000
+CIPHERTEXT = 79bf5dce14bb7dd73a8e3611de7ce026
+
+COUNT = 102
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffe000000
+CIPHERTEXT = 3c849939a5d29399f344c4a0eca8a576
+
+COUNT = 103
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffff000000
+CIPHERTEXT = ed3c0a94d59bece98835da7aa4f07ca2
+
+COUNT = 104
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffff800000
+CIPHERTEXT = 63919ed4ce10196438b6ad09d99cd795
+
+COUNT = 105
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffc00000
+CIPHERTEXT = 7678f3a833f19fea95f3c6029e2bc610
+
+COUNT = 106
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffe00000
+CIPHERTEXT = 3aa426831067d36b92be7c5f81c13c56
+
+COUNT = 107
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffff00000
+CIPHERTEXT = 9272e2d2cdd11050998c845077a30ea0
+
+COUNT = 108
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffff80000
+CIPHERTEXT = 088c4b53f5ec0ff814c19adae7f6246c
+
+COUNT = 109
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffc0000
+CIPHERTEXT = 4010a5e401fdf0a0354ddbcc0d012b17
+
+COUNT = 110
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffe0000
+CIPHERTEXT = a87a385736c0a6189bd6589bd8445a93
+
+COUNT = 111
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffff0000
+CIPHERTEXT = 545f2b83d9616dccf60fa9830e9cd287
+
+COUNT = 112
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffff8000
+CIPHERTEXT = 4b706f7f92406352394037a6d4f4688d
+
+COUNT = 113
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffc000
+CIPHERTEXT = b7972b3941c44b90afa7b264bfba7387
+
+COUNT = 114
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffe000
+CIPHERTEXT = 6f45732cf10881546f0fd23896d2bb60
+
+COUNT = 115
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffff000
+CIPHERTEXT = 2e3579ca15af27f64b3c955a5bfc30ba
+
+COUNT = 116
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffff800
+CIPHERTEXT = 34a2c5a91ae2aec99b7d1b5fa6780447
+
+COUNT = 117
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffc00
+CIPHERTEXT = a4d6616bd04f87335b0e53351227a9ee
+
+COUNT = 118
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffe00
+CIPHERTEXT = 7f692b03945867d16179a8cefc83ea3f
+
+COUNT = 119
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffff00
+CIPHERTEXT = 3bd141ee84a0e6414a26e7a4f281f8a2
+
+COUNT = 120
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffff80
+CIPHERTEXT = d1788f572d98b2b16ec5d5f3922b99bc
+
+COUNT = 121
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffffc0
+CIPHERTEXT = 0833ff6f61d98a57b288e8c3586b85a6
+
+COUNT = 122
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffffe0
+CIPHERTEXT = 8568261797de176bf0b43becc6285afb
+
+COUNT = 123
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffff0
+CIPHERTEXT = f9b0fda0c4a898f5b9e6f661c4ce4d07
+
+COUNT = 124
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffff8
+CIPHERTEXT = 8ade895913685c67c5269f8aae42983e
+
+COUNT = 125
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffffc
+CIPHERTEXT = 39bde67d5c8ed8a8b1c37eb8fa9f5ac0
+
+COUNT = 126
+KEY = 00000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffffe
+CIPHERTEXT = 5c005e72c1418c44f569f2ea33ba54f3
+
+COUNT = 127
+KEY = 00000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffffff
+CIPHERTEXT = 3f5b8cc9ea855a0afa7347d23e8d664e
+
+
+ECB Varying Key 128 bits
+
+COUNT = 0
+KEY = 80000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 0edd33d3c621e546455bd8ba1418bec8
+
+COUNT = 1
+KEY = c0000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4bc3f883450c113c64ca42e1112a9e87
+
+COUNT = 2
+KEY = e0000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 72a1da770f5d7ac4c9ef94d822affd97
+
+COUNT = 3
+KEY = f0000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 970014d634e2b7650777e8e84d03ccd8
+
+COUNT = 4
+KEY = f8000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f17e79aed0db7e279e955b5f493875a7
+
+COUNT = 5
+KEY = fc000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9ed5a75136a940d0963da379db4af26a
+
+COUNT = 6
+KEY = fe000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c4295f83465c7755e8fa364bac6a7ea5
+
+COUNT = 7
+KEY = ff000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b1d758256b28fd850ad4944208cf1155
+
+COUNT = 8
+KEY = ff800000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 42ffb34c743de4d88ca38011c990890b
+
+COUNT = 9
+KEY = ffc00000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9958f0ecea8b2172c0c1995f9182c0f3
+
+COUNT = 10
+KEY = ffe00000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 956d7798fac20f82a8823f984d06f7f5
+
+COUNT = 11
+KEY = fff00000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a01bf44f2d16be928ca44aaf7b9b106b
+
+COUNT = 12
+KEY = fff80000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b5f1a33e50d40d103764c76bd4c6b6f8
+
+COUNT = 13
+KEY = fffc0000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2637050c9fc0d4817e2d69de878aee8d
+
+COUNT = 14
+KEY = fffe0000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 113ecbe4a453269a0dd26069467fb5b5
+
+COUNT = 15
+KEY = ffff0000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 97d0754fe68f11b9e375d070a608c884
+
+COUNT = 16
+KEY = ffff8000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c6a0b3e998d05068a5399778405200b4
+
+COUNT = 17
+KEY = ffffc000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = df556a33438db87bc41b1752c55e5e49
+
+COUNT = 18
+KEY = ffffe000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 90fb128d3a1af6e548521bb962bf1f05
+
+COUNT = 19
+KEY = fffff000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 26298e9c1db517c215fadfb7d2a8d691
+
+COUNT = 20
+KEY = fffff800000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a6cb761d61f8292d0df393a279ad0380
+
+COUNT = 21
+KEY = fffffc00000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 12acd89b13cd5f8726e34d44fd486108
+
+COUNT = 22
+KEY = fffffe00000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 95b1703fc57ba09fe0c3580febdd7ed4
+
+COUNT = 23
+KEY = ffffff00000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = de11722d893e9f9121c381becc1da59a
+
+COUNT = 24
+KEY = ffffff80000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6d114ccb27bf391012e8974c546d9bf2
+
+COUNT = 25
+KEY = ffffffc0000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5ce37e17eb4646ecfac29b9cc38d9340
+
+COUNT = 26
+KEY = ffffffe0000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 18c1b6e2157122056d0243d8a165cddb
+
+COUNT = 27
+KEY = fffffff0000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 99693e6a59d1366c74d823562d7e1431
+
+COUNT = 28
+KEY = fffffff8000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6c7c64dc84a8bba758ed17eb025a57e3
+
+COUNT = 29
+KEY = fffffffc000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e17bc79f30eaab2fac2cbbe3458d687a
+
+COUNT = 30
+KEY = fffffffe000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1114bc2028009b923f0b01915ce5e7c4
+
+COUNT = 31
+KEY = ffffffff000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9c28524a16a1e1c1452971caa8d13476
+
+COUNT = 32
+KEY = ffffffff800000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ed62e16363638360fdd6ad62112794f0
+
+COUNT = 33
+KEY = ffffffffc00000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5a8688f0b2a2c16224c161658ffd4044
+
+COUNT = 34
+KEY = ffffffffe00000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 23f710842b9bb9c32f26648c786807ca
+
+COUNT = 35
+KEY = fffffffff00000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 44a98bf11e163f632c47ec6a49683a89
+
+COUNT = 36
+KEY = fffffffff80000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 0f18aff94274696d9b61848bd50ac5e5
+
+COUNT = 37
+KEY = fffffffffc0000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 82408571c3e2424540207f833b6dda69
+
+COUNT = 38
+KEY = fffffffffe0000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 303ff996947f0c7d1f43c8f3027b9b75
+
+COUNT = 39
+KEY = ffffffffff0000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7df4daf4ad29a3615a9b6ece5c99518a
+
+COUNT = 40
+KEY = ffffffffff8000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c72954a48d0774db0b4971c526260415
+
+COUNT = 41
+KEY = ffffffffffc000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1df9b76112dc6531e07d2cfda04411f0
+
+COUNT = 42
+KEY = ffffffffffe000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8e4d8e699119e1fc87545a647fb1d34f
+
+COUNT = 43
+KEY = fffffffffff000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e6c4807ae11f36f091c57d9fb68548d1
+
+COUNT = 44
+KEY = fffffffffff800000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8ebf73aad49c82007f77a5c1ccec6ab4
+
+COUNT = 45
+KEY = fffffffffffc00000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4fb288cc2040049001d2c7585ad123fc
+
+COUNT = 46
+KEY = fffffffffffe00000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 04497110efb9dceb13e2b13fb4465564
+
+COUNT = 47
+KEY = ffffffffffff00000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 75550e6cb5a88e49634c9ab69eda0430
+
+COUNT = 48
+KEY = ffffffffffff80000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b6768473ce9843ea66a81405dd50b345
+
+COUNT = 49
+KEY = ffffffffffffc0000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cb2f430383f9084e03a653571e065de6
+
+COUNT = 50
+KEY = ffffffffffffe0000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ff4e66c07bae3e79fb7d210847a3b0ba
+
+COUNT = 51
+KEY = fffffffffffff0000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7b90785125505fad59b13c186dd66ce3
+
+COUNT = 52
+KEY = fffffffffffff8000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8b527a6aebdaec9eaef8eda2cb7783e5
+
+COUNT = 53
+KEY = fffffffffffffc000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 43fdaf53ebbc9880c228617d6a9b548b
+
+COUNT = 54
+KEY = fffffffffffffe000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 53786104b9744b98f052c46f1c850d0b
+
+COUNT = 55
+KEY = ffffffffffffff000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b5ab3013dd1e61df06cbaf34ca2aee78
+
+COUNT = 56
+KEY = ffffffffffffff800000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7470469be9723030fdcc73a8cd4fbb10
+
+COUNT = 57
+KEY = ffffffffffffffc00000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a35a63f5343ebe9ef8167bcb48ad122e
+
+COUNT = 58
+KEY = ffffffffffffffe00000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fd8687f0757a210e9fdf181204c30863
+
+COUNT = 59
+KEY = fffffffffffffff00000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7a181e84bd5457d26a88fbae96018fb0
+
+COUNT = 60
+KEY = fffffffffffffff80000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 653317b9362b6f9b9e1a580e68d494b5
+
+COUNT = 61
+KEY = fffffffffffffffc0000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 995c9dc0b689f03c45867b5faa5c18d1
+
+COUNT = 62
+KEY = fffffffffffffffe0000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 77a4d96d56dda398b9aabecfc75729fd
+
+COUNT = 63
+KEY = ffffffffffffffff0000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 84be19e053635f09f2665e7bae85b42d
+
+COUNT = 64
+KEY = ffffffffffffffff8000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 32cd652842926aea4aa6137bb2be2b5e
+
+COUNT = 65
+KEY = ffffffffffffffffc000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 493d4a4f38ebb337d10aa84e9171a554
+
+COUNT = 66
+KEY = ffffffffffffffffe000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d9bff7ff454b0ec5a4a2a69566e2cb84
+
+COUNT = 67
+KEY = fffffffffffffffff000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3535d565ace3f31eb249ba2cc6765d7a
+
+COUNT = 68
+KEY = fffffffffffffffff800000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f60e91fc3269eecf3231c6e9945697c6
+
+COUNT = 69
+KEY = fffffffffffffffffc00000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ab69cfadf51f8e604d9cc37182f6635a
+
+COUNT = 70
+KEY = fffffffffffffffffe00000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7866373f24a0b6ed56e0d96fcdafb877
+
+COUNT = 71
+KEY = ffffffffffffffffff00000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1ea448c2aac954f5d812e9d78494446a
+
+COUNT = 72
+KEY = ffffffffffffffffff80000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = acc5599dd8ac02239a0fef4a36dd1668
+
+COUNT = 73
+KEY = ffffffffffffffffffc0000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d8764468bb103828cf7e1473ce895073
+
+COUNT = 74
+KEY = ffffffffffffffffffe0000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1b0d02893683b9f180458e4aa6b73982
+
+COUNT = 75
+KEY = fffffffffffffffffff0000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 96d9b017d302df410a937dcdb8bb6e43
+
+COUNT = 76
+KEY = fffffffffffffffffff8000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ef1623cc44313cff440b1594a7e21cc6
+
+COUNT = 77
+KEY = fffffffffffffffffffc000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 284ca2fa35807b8b0ae4d19e11d7dbd7
+
+COUNT = 78
+KEY = fffffffffffffffffffe000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f2e976875755f9401d54f36e2a23a594
+
+COUNT = 79
+KEY = ffffffffffffffffffff000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ec198a18e10e532403b7e20887c8dd80
+
+COUNT = 80
+KEY = ffffffffffffffffffff800000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 545d50ebd919e4a6949d96ad47e46a80
+
+COUNT = 81
+KEY = ffffffffffffffffffffc00000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = dbdfb527060e0a71009c7bb0c68f1d44
+
+COUNT = 82
+KEY = ffffffffffffffffffffe00000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9cfa1322ea33da2173a024f2ff0d896d
+
+COUNT = 83
+KEY = fffffffffffffffffffff00000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8785b1a75b0f3bd958dcd0e29318c521
+
+COUNT = 84
+KEY = fffffffffffffffffffff80000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 38f67b9e98e4a97b6df030a9fcdd0104
+
+COUNT = 85
+KEY = fffffffffffffffffffffc0000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 192afffb2c880e82b05926d0fc6c448b
+
+COUNT = 86
+KEY = fffffffffffffffffffffe0000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6a7980ce7b105cf530952d74daaf798c
+
+COUNT = 87
+KEY = ffffffffffffffffffffff0000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ea3695e1351b9d6858bd958cf513ef6c
+
+COUNT = 88
+KEY = ffffffffffffffffffffff8000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6da0490ba0ba0343b935681d2cce5ba1
+
+COUNT = 89
+KEY = ffffffffffffffffffffffc000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f0ea23af08534011c60009ab29ada2f1
+
+COUNT = 90
+KEY = ffffffffffffffffffffffe000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ff13806cf19cc38721554d7c0fcdcd4b
+
+COUNT = 91
+KEY = fffffffffffffffffffffff000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6838af1f4f69bae9d85dd188dcdf0688
+
+COUNT = 92
+KEY = fffffffffffffffffffffff800000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 36cf44c92d550bfb1ed28ef583ddf5d7
+
+COUNT = 93
+KEY = fffffffffffffffffffffffc00000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d06e3195b5376f109d5c4ec6c5d62ced
+
+COUNT = 94
+KEY = fffffffffffffffffffffffe00000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c440de014d3d610707279b13242a5c36
+
+COUNT = 95
+KEY = ffffffffffffffffffffffff00000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f0c5c6ffa5e0bd3a94c88f6b6f7c16b9
+
+COUNT = 96
+KEY = ffffffffffffffffffffffff80000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3e40c3901cd7effc22bffc35dee0b4d9
+
+COUNT = 97
+KEY = ffffffffffffffffffffffffc0000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b63305c72bedfab97382c406d0c49bc6
+
+COUNT = 98
+KEY = ffffffffffffffffffffffffe0000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 36bbaab22a6bd4925a99a2b408d2dbae
+
+COUNT = 99
+KEY = fffffffffffffffffffffffff0000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 307c5b8fcd0533ab98bc51e27a6ce461
+
+COUNT = 100
+KEY = fffffffffffffffffffffffff8000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 829c04ff4c07513c0b3ef05c03e337b5
+
+COUNT = 101
+KEY = fffffffffffffffffffffffffc000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f17af0e895dda5eb98efc68066e84c54
+
+COUNT = 102
+KEY = fffffffffffffffffffffffffe000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 277167f3812afff1ffacb4a934379fc3
+
+COUNT = 103
+KEY = ffffffffffffffffffffffffff000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2cb1dc3a9c72972e425ae2ef3eb597cd
+
+COUNT = 104
+KEY = ffffffffffffffffffffffffff800000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 36aeaa3a213e968d4b5b679d3a2c97fe
+
+COUNT = 105
+KEY = ffffffffffffffffffffffffffc00000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9241daca4fdd034a82372db50e1a0f3f
+
+COUNT = 106
+KEY = ffffffffffffffffffffffffffe00000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c14574d9cd00cf2b5a7f77e53cd57885
+
+COUNT = 107
+KEY = fffffffffffffffffffffffffff00000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 793de39236570aba83ab9b737cb521c9
+
+COUNT = 108
+KEY = fffffffffffffffffffffffffff80000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 16591c0f27d60e29b85a96c33861a7ef
+
+COUNT = 109
+KEY = fffffffffffffffffffffffffffc0000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 44fb5c4d4f5cb79be5c174a3b1c97348
+
+COUNT = 110
+KEY = fffffffffffffffffffffffffffe0000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 674d2b61633d162be59dde04222f4740
+
+COUNT = 111
+KEY = ffffffffffffffffffffffffffff0000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b4750ff263a65e1f9e924ccfd98f3e37
+
+COUNT = 112
+KEY = ffffffffffffffffffffffffffff8000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 62d0662d6eaeddedebae7f7ea3a4f6b6
+
+COUNT = 113
+KEY = ffffffffffffffffffffffffffffc000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 70c46bb30692be657f7eaa93ebad9897
+
+COUNT = 114
+KEY = ffffffffffffffffffffffffffffe000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 323994cfb9da285a5d9642e1759b224a
+
+COUNT = 115
+KEY = fffffffffffffffffffffffffffff000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1dbf57877b7b17385c85d0b54851e371
+
+COUNT = 116
+KEY = fffffffffffffffffffffffffffff800
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = dfa5c097cdc1532ac071d57b1d28d1bd
+
+COUNT = 117
+KEY = fffffffffffffffffffffffffffffc00
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3a0c53fa37311fc10bd2a9981f513174
+
+COUNT = 118
+KEY = fffffffffffffffffffffffffffffe00
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ba4f970c0a25c41814bdae2e506be3b4
+
+COUNT = 119
+KEY = ffffffffffffffffffffffffffffff00
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2dce3acb727cd13ccd76d425ea56e4f6
+
+COUNT = 120
+KEY = ffffffffffffffffffffffffffffff80
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5160474d504b9b3eefb68d35f245f4b3
+
+COUNT = 121
+KEY = ffffffffffffffffffffffffffffffc0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 41a8a947766635dec37553d9a6c0cbb7
+
+COUNT = 122
+KEY = ffffffffffffffffffffffffffffffe0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 25d6cfe6881f2bf497dd14cd4ddf445b
+
+COUNT = 123
+KEY = fffffffffffffffffffffffffffffff0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 41c78c135ed9e98c096640647265da1e
+
+COUNT = 124
+KEY = fffffffffffffffffffffffffffffff8
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5a4d404d8917e353e92a21072c3b2305
+
+COUNT = 125
+KEY = fffffffffffffffffffffffffffffffc
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 02bc96846b3fdc71643f384cd3cc3eaf
+
+COUNT = 126
+KEY = fffffffffffffffffffffffffffffffe
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9ba4a9143f4e5d4048521c4f8877d88e
+
+COUNT = 127
+KEY = ffffffffffffffffffffffffffffffff
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a1f6258c877d5fcd8964484538bfc92c
+
+
+ECB Varying Plaintext 192 bits
+
+COUNT = 0
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = 80000000000000000000000000000000
+CIPHERTEXT = 6cd02513e8d4dc986b4afe087a60bd0c
+
+COUNT = 1
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = c0000000000000000000000000000000
+CIPHERTEXT = 2ce1f8b7e30627c1c4519eada44bc436
+
+COUNT = 2
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = e0000000000000000000000000000000
+CIPHERTEXT = 9946b5f87af446f5796c1fee63a2da24
+
+COUNT = 3
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = f0000000000000000000000000000000
+CIPHERTEXT = 2a560364ce529efc21788779568d5555
+
+COUNT = 4
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = f8000000000000000000000000000000
+CIPHERTEXT = 35c1471837af446153bce55d5ba72a0a
+
+COUNT = 5
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fc000000000000000000000000000000
+CIPHERTEXT = ce60bc52386234f158f84341e534cd9e
+
+COUNT = 6
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fe000000000000000000000000000000
+CIPHERTEXT = 8c7c27ff32bcf8dc2dc57c90c2903961
+
+COUNT = 7
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ff000000000000000000000000000000
+CIPHERTEXT = 32bb6a7ec84499e166f936003d55a5bb
+
+COUNT = 8
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ff800000000000000000000000000000
+CIPHERTEXT = a5c772e5c62631ef660ee1d5877f6d1b
+
+COUNT = 9
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffc00000000000000000000000000000
+CIPHERTEXT = 030d7e5b64f380a7e4ea5387b5cd7f49
+
+COUNT = 10
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffe00000000000000000000000000000
+CIPHERTEXT = 0dc9a2610037009b698f11bb7e86c83e
+
+COUNT = 11
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fff00000000000000000000000000000
+CIPHERTEXT = 0046612c766d1840c226364f1fa7ed72
+
+COUNT = 12
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fff80000000000000000000000000000
+CIPHERTEXT = 4880c7e08f27befe78590743c05e698b
+
+COUNT = 13
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffc0000000000000000000000000000
+CIPHERTEXT = 2520ce829a26577f0f4822c4ecc87401
+
+COUNT = 14
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffe0000000000000000000000000000
+CIPHERTEXT = 8765e8acc169758319cb46dc7bcf3dca
+
+COUNT = 15
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffff0000000000000000000000000000
+CIPHERTEXT = e98f4ba4f073df4baa116d011dc24a28
+
+COUNT = 16
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffff8000000000000000000000000000
+CIPHERTEXT = f378f68c5dbf59e211b3a659a7317d94
+
+COUNT = 17
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffc000000000000000000000000000
+CIPHERTEXT = 283d3b069d8eb9fb432d74b96ca762b4
+
+COUNT = 18
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffe000000000000000000000000000
+CIPHERTEXT = a7e1842e8a87861c221a500883245c51
+
+COUNT = 19
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffff000000000000000000000000000
+CIPHERTEXT = 77aa270471881be070fb52c7067ce732
+
+COUNT = 20
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffff800000000000000000000000000
+CIPHERTEXT = 01b0f476d484f43f1aeb6efa9361a8ac
+
+COUNT = 21
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffc00000000000000000000000000
+CIPHERTEXT = 1c3a94f1c052c55c2d8359aff2163b4f
+
+COUNT = 22
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffe00000000000000000000000000
+CIPHERTEXT = e8a067b604d5373d8b0f2e05a03b341b
+
+COUNT = 23
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffff00000000000000000000000000
+CIPHERTEXT = a7876ec87f5a09bfea42c77da30fd50e
+
+COUNT = 24
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffff80000000000000000000000000
+CIPHERTEXT = 0cf3e9d3a42be5b854ca65b13f35f48d
+
+COUNT = 25
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffc0000000000000000000000000
+CIPHERTEXT = 6c62f6bbcab7c3e821c9290f08892dda
+
+COUNT = 26
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffe0000000000000000000000000
+CIPHERTEXT = 7f5e05bd2068738196fee79ace7e3aec
+
+COUNT = 27
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffff0000000000000000000000000
+CIPHERTEXT = 440e0d733255cda92fb46e842fe58054
+
+COUNT = 28
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffff8000000000000000000000000
+CIPHERTEXT = aa5d5b1c4ea1b7a22e5583ac2e9ed8a7
+
+COUNT = 29
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffc000000000000000000000000
+CIPHERTEXT = 77e537e89e8491e8662aae3bc809421d
+
+COUNT = 30
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffe000000000000000000000000
+CIPHERTEXT = 997dd3e9f1598bfa73f75973f7e93b76
+
+COUNT = 31
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffff000000000000000000000000
+CIPHERTEXT = 1b38d4f7452afefcb7fc721244e4b72e
+
+COUNT = 32
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffff800000000000000000000000
+CIPHERTEXT = 0be2b18252e774dda30cdda02c6906e3
+
+COUNT = 33
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffc00000000000000000000000
+CIPHERTEXT = d2695e59c20361d82652d7d58b6f11b2
+
+COUNT = 34
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffe00000000000000000000000
+CIPHERTEXT = 902d88d13eae52089abd6143cfe394e9
+
+COUNT = 35
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffff00000000000000000000000
+CIPHERTEXT = d49bceb3b823fedd602c305345734bd2
+
+COUNT = 36
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffff80000000000000000000000
+CIPHERTEXT = 707b1dbb0ffa40ef7d95def421233fae
+
+COUNT = 37
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffc0000000000000000000000
+CIPHERTEXT = 7ca0c1d93356d9eb8aa952084d75f913
+
+COUNT = 38
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffe0000000000000000000000
+CIPHERTEXT = f2cbf9cb186e270dd7bdb0c28febc57d
+
+COUNT = 39
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffff0000000000000000000000
+CIPHERTEXT = c94337c37c4e790ab45780bd9c3674a0
+
+COUNT = 40
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffff8000000000000000000000
+CIPHERTEXT = 8e3558c135252fb9c9f367ed609467a1
+
+COUNT = 41
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffc000000000000000000000
+CIPHERTEXT = 1b72eeaee4899b443914e5b3a57fba92
+
+COUNT = 42
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffe000000000000000000000
+CIPHERTEXT = 011865f91bc56868d051e52c9efd59b7
+
+COUNT = 43
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffff000000000000000000000
+CIPHERTEXT = e4771318ad7a63dd680f6e583b7747ea
+
+COUNT = 44
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffff800000000000000000000
+CIPHERTEXT = 61e3d194088dc8d97e9e6db37457eac5
+
+COUNT = 45
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffc00000000000000000000
+CIPHERTEXT = 36ff1ec9ccfbc349e5d356d063693ad6
+
+COUNT = 46
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffe00000000000000000000
+CIPHERTEXT = 3cc9e9a9be8cc3f6fb2ea24088e9bb19
+
+COUNT = 47
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffff00000000000000000000
+CIPHERTEXT = 1ee5ab003dc8722e74905d9a8fe3d350
+
+COUNT = 48
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffff80000000000000000000
+CIPHERTEXT = 245339319584b0a412412869d6c2eada
+
+COUNT = 49
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffc0000000000000000000
+CIPHERTEXT = 7bd496918115d14ed5380852716c8814
+
+COUNT = 50
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffe0000000000000000000
+CIPHERTEXT = 273ab2f2b4a366a57d582a339313c8b1
+
+COUNT = 51
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffff0000000000000000000
+CIPHERTEXT = 113365a9ffbe3b0ca61e98507554168b
+
+COUNT = 52
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffff8000000000000000000
+CIPHERTEXT = afa99c997ac478a0dea4119c9e45f8b1
+
+COUNT = 53
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffc000000000000000000
+CIPHERTEXT = 9216309a7842430b83ffb98638011512
+
+COUNT = 54
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffe000000000000000000
+CIPHERTEXT = 62abc792288258492a7cb45145f4b759
+
+COUNT = 55
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffff000000000000000000
+CIPHERTEXT = 534923c169d504d7519c15d30e756c50
+
+COUNT = 56
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffff800000000000000000
+CIPHERTEXT = fa75e05bcdc7e00c273fa33f6ee441d2
+
+COUNT = 57
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffc00000000000000000
+CIPHERTEXT = 7d350fa6057080f1086a56b17ec240db
+
+COUNT = 58
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffe00000000000000000
+CIPHERTEXT = f34e4a6324ea4a5c39a661c8fe5ada8f
+
+COUNT = 59
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffff00000000000000000
+CIPHERTEXT = 0882a16f44088d42447a29ac090ec17e
+
+COUNT = 60
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffff80000000000000000
+CIPHERTEXT = 3a3c15bfc11a9537c130687004e136ee
+
+COUNT = 61
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffc0000000000000000
+CIPHERTEXT = 22c0a7678dc6d8cf5c8a6d5a9960767c
+
+COUNT = 62
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffe0000000000000000
+CIPHERTEXT = b46b09809d68b9a456432a79bdc2e38c
+
+COUNT = 63
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffff0000000000000000
+CIPHERTEXT = 93baaffb35fbe739c17c6ac22eecf18f
+
+COUNT = 64
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffff8000000000000000
+CIPHERTEXT = c8aa80a7850675bc007c46df06b49868
+
+COUNT = 65
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffc000000000000000
+CIPHERTEXT = 12c6f3877af421a918a84b775858021d
+
+COUNT = 66
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffe000000000000000
+CIPHERTEXT = 33f123282c5d633924f7d5ba3f3cab11
+
+COUNT = 67
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffff000000000000000
+CIPHERTEXT = a8f161002733e93ca4527d22c1a0c5bb
+
+COUNT = 68
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffff800000000000000
+CIPHERTEXT = b72f70ebf3e3fda23f508eec76b42c02
+
+COUNT = 69
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffc00000000000000
+CIPHERTEXT = 6a9d965e6274143f25afdcfc88ffd77c
+
+COUNT = 70
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffe00000000000000
+CIPHERTEXT = a0c74fd0b9361764ce91c5200b095357
+
+COUNT = 71
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffff00000000000000
+CIPHERTEXT = 091d1fdc2bd2c346cd5046a8c6209146
+
+COUNT = 72
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffff80000000000000
+CIPHERTEXT = e2a37580116cfb71856254496ab0aca8
+
+COUNT = 73
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffc0000000000000
+CIPHERTEXT = e0b3a00785917c7efc9adba322813571
+
+COUNT = 74
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffe0000000000000
+CIPHERTEXT = 733d41f4727b5ef0df4af4cf3cffa0cb
+
+COUNT = 75
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffff0000000000000
+CIPHERTEXT = a99ebb030260826f981ad3e64490aa4f
+
+COUNT = 76
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffff8000000000000
+CIPHERTEXT = 73f34c7d3eae5e80082c1647524308ee
+
+COUNT = 77
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffc000000000000
+CIPHERTEXT = 40ebd5ad082345b7a2097ccd3464da02
+
+COUNT = 78
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffe000000000000
+CIPHERTEXT = 7cc4ae9a424b2cec90c97153c2457ec5
+
+COUNT = 79
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffff000000000000
+CIPHERTEXT = 54d632d03aba0bd0f91877ebdd4d09cb
+
+COUNT = 80
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffff800000000000
+CIPHERTEXT = d3427be7e4d27cd54f5fe37b03cf0897
+
+COUNT = 81
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffc00000000000
+CIPHERTEXT = b2099795e88cc158fd75ea133d7e7fbe
+
+COUNT = 82
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffe00000000000
+CIPHERTEXT = a6cae46fb6fadfe7a2c302a34242817b
+
+COUNT = 83
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffff00000000000
+CIPHERTEXT = 026a7024d6a902e0b3ffccbaa910cc3f
+
+COUNT = 84
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffff80000000000
+CIPHERTEXT = 156f07767a85a4312321f63968338a01
+
+COUNT = 85
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffc0000000000
+CIPHERTEXT = 15eec9ebf42b9ca76897d2cd6c5a12e2
+
+COUNT = 86
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffe0000000000
+CIPHERTEXT = db0d3a6fdcc13f915e2b302ceeb70fd8
+
+COUNT = 87
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffff0000000000
+CIPHERTEXT = 71dbf37e87a2e34d15b20e8f10e48924
+
+COUNT = 88
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffff8000000000
+CIPHERTEXT = c745c451e96ff3c045e4367c833e3b54
+
+COUNT = 89
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffc000000000
+CIPHERTEXT = 340da09c2dd11c3b679d08ccd27dd595
+
+COUNT = 90
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffe000000000
+CIPHERTEXT = 8279f7c0c2a03ee660c6d392db025d18
+
+COUNT = 91
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffff000000000
+CIPHERTEXT = a4b2c7d8eba531ff47c5041a55fbd1ec
+
+COUNT = 92
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffff800000000
+CIPHERTEXT = 74569a2ca5a7bd5131ce8dc7cbfbf72f
+
+COUNT = 93
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffc00000000
+CIPHERTEXT = 3713da0c0219b63454035613b5a403dd
+
+COUNT = 94
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffe00000000
+CIPHERTEXT = 8827551ddcc9df23fa72a3de4e9f0b07
+
+COUNT = 95
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffff00000000
+CIPHERTEXT = 2e3febfd625bfcd0a2c06eb460da1732
+
+COUNT = 96
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffff80000000
+CIPHERTEXT = ee82e6ba488156f76496311da6941deb
+
+COUNT = 97
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffc0000000
+CIPHERTEXT = 4770446f01d1f391256e85a1b30d89d3
+
+COUNT = 98
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffe0000000
+CIPHERTEXT = af04b68f104f21ef2afb4767cf74143c
+
+COUNT = 99
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffff0000000
+CIPHERTEXT = cf3579a9ba38c8e43653173e14f3a4c6
+
+COUNT = 100
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffff8000000
+CIPHERTEXT = b3bba904f4953e09b54800af2f62e7d4
+
+COUNT = 101
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffc000000
+CIPHERTEXT = fc4249656e14b29eb9c44829b4c59a46
+
+COUNT = 102
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffe000000
+CIPHERTEXT = 9b31568febe81cfc2e65af1c86d1a308
+
+COUNT = 103
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffff000000
+CIPHERTEXT = 9ca09c25f273a766db98a480ce8dfedc
+
+COUNT = 104
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffff800000
+CIPHERTEXT = b909925786f34c3c92d971883c9fbedf
+
+COUNT = 105
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffc00000
+CIPHERTEXT = 82647f1332fe570a9d4d92b2ee771d3b
+
+COUNT = 106
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffe00000
+CIPHERTEXT = 3604a7e80832b3a99954bca6f5b9f501
+
+COUNT = 107
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffff00000
+CIPHERTEXT = 884607b128c5de3ab39a529a1ef51bef
+
+COUNT = 108
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffff80000
+CIPHERTEXT = 670cfa093d1dbdb2317041404102435e
+
+COUNT = 109
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffc0000
+CIPHERTEXT = 7a867195f3ce8769cbd336502fbb5130
+
+COUNT = 110
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffe0000
+CIPHERTEXT = 52efcf64c72b2f7ca5b3c836b1078c15
+
+COUNT = 111
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffff0000
+CIPHERTEXT = 4019250f6eefb2ac5ccbcae044e75c7e
+
+COUNT = 112
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffff8000
+CIPHERTEXT = 022c4f6f5a017d292785627667ddef24
+
+COUNT = 113
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffc000
+CIPHERTEXT = e9c21078a2eb7e03250f71000fa9e3ed
+
+COUNT = 114
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffe000
+CIPHERTEXT = a13eaeeb9cd391da4e2b09490b3e7fad
+
+COUNT = 115
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffff000
+CIPHERTEXT = c958a171dca1d4ed53e1af1d380803a9
+
+COUNT = 116
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffff800
+CIPHERTEXT = 21442e07a110667f2583eaeeee44dc8c
+
+COUNT = 117
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffc00
+CIPHERTEXT = 59bbb353cf1dd867a6e33737af655e99
+
+COUNT = 118
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffe00
+CIPHERTEXT = 43cd3b25375d0ce41087ff9fe2829639
+
+COUNT = 119
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffff00
+CIPHERTEXT = 6b98b17e80d1118e3516bd768b285a84
+
+COUNT = 120
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffff80
+CIPHERTEXT = ae47ed3676ca0c08deea02d95b81db58
+
+COUNT = 121
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffffc0
+CIPHERTEXT = 34ec40dc20413795ed53628ea748720b
+
+COUNT = 122
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffffe0
+CIPHERTEXT = 4dc68163f8e9835473253542c8a65d46
+
+COUNT = 123
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffff0
+CIPHERTEXT = 2aabb999f43693175af65c6c612c46fb
+
+COUNT = 124
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffff8
+CIPHERTEXT = e01f94499dac3547515c5b1d756f0f58
+
+COUNT = 125
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffffc
+CIPHERTEXT = 9d12435a46480ce00ea349f71799df9a
+
+COUNT = 126
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffffe
+CIPHERTEXT = cef41d16d266bdfe46938ad7884cc0cf
+
+COUNT = 127
+KEY = 000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffffff
+CIPHERTEXT = b13db4da1f718bc6904797c82bcf2d32
+
+
+ECB Varying Key 192 bits
+
+COUNT = 0
+KEY = 800000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = de885dc87f5a92594082d02cc1e1b42c
+
+COUNT = 1
+KEY = c00000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 132b074e80f2a597bf5febd8ea5da55e
+
+COUNT = 2
+KEY = e00000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6eccedf8de592c22fb81347b79f2db1f
+
+COUNT = 3
+KEY = f00000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 180b09f267c45145db2f826c2582d35c
+
+COUNT = 4
+KEY = f80000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = edd807ef7652d7eb0e13c8b5e15b3bc0
+
+COUNT = 5
+KEY = fc0000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9978bcf8dd8fd72241223ad24b31b8a4
+
+COUNT = 6
+KEY = fe0000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5310f654343e8f27e12c83a48d24ff81
+
+COUNT = 7
+KEY = ff0000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 833f71258d53036b02952c76c744f5a1
+
+COUNT = 8
+KEY = ff8000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = eba83ff200cff9318a92f8691a06b09f
+
+COUNT = 9
+KEY = ffc000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ff620ccbe9f3292abdf2176b09f04eba
+
+COUNT = 10
+KEY = ffe000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7ababc4b3f516c9aafb35f4140b548f9
+
+COUNT = 11
+KEY = fff000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = aa187824d9c4582b0916493ecbde8c57
+
+COUNT = 12
+KEY = fff800000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1c0ad553177fd5ea1092c9d626a29dc4
+
+COUNT = 13
+KEY = fffc00000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a5dc46c37261194124ecaebd680408ec
+
+COUNT = 14
+KEY = fffe00000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e4f2f2ae23e9b10bacfa58601531ba54
+
+COUNT = 15
+KEY = ffff00000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b7d67cf1a1e91e8ff3a57a172c7bf412
+
+COUNT = 16
+KEY = ffff80000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 26706be06967884e847d137128ce47b3
+
+COUNT = 17
+KEY = ffffc0000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b2f8b409b0585909aad3a7b5a219072a
+
+COUNT = 18
+KEY = ffffe0000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5e4b7bff0290c78344c54a23b722cd20
+
+COUNT = 19
+KEY = fffff0000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 07093657552d4414227ce161e9ebf7dd
+
+COUNT = 20
+KEY = fffff8000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e1af1e7d8bc225ed4dffb771ecbb9e67
+
+COUNT = 21
+KEY = fffffc000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ef6555253635d8432156cfd9c11b145a
+
+COUNT = 22
+KEY = fffffe000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fb4035074a5d4260c90cbd6da6c3fceb
+
+COUNT = 23
+KEY = ffffff000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 446ee416f9ad1c103eb0cc96751c88e1
+
+COUNT = 24
+KEY = ffffff800000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 198ae2a4637ac0a7890a8fd1485445c9
+
+COUNT = 25
+KEY = ffffffc00000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 562012ec8faded0825fb2fa70ab30cbd
+
+COUNT = 26
+KEY = ffffffe00000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cc8a64b46b5d88bf7f247d4dbaf38f05
+
+COUNT = 27
+KEY = fffffff00000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a168253762e2cc81b42d1e5001762699
+
+COUNT = 28
+KEY = fffffff80000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1b41f83b38ce5032c6cd7af98cf62061
+
+COUNT = 29
+KEY = fffffffc0000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 61a89990cd1411750d5fb0dc988447d4
+
+COUNT = 30
+KEY = fffffffe0000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b5accc8ed629edf8c68a539183b1ea82
+
+COUNT = 31
+KEY = ffffffff0000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b16fa71f846b81a13f361c43a851f290
+
+COUNT = 32
+KEY = ffffffff8000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4fad6efdff5975aee7692234bcd54488
+
+COUNT = 33
+KEY = ffffffffc000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ebfdb05a783d03082dfe5fdd80a00b17
+
+COUNT = 34
+KEY = ffffffffe000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = eb81b584766997af6ba5529d3bdd8609
+
+COUNT = 35
+KEY = fffffffff000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 0cf4ff4f49c8a0ca060c443499e29313
+
+COUNT = 36
+KEY = fffffffff800000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cc4ba8a8e029f8b26d8afff9df133bb6
+
+COUNT = 37
+KEY = fffffffffc00000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fefebf64360f38e4e63558f0ffc550c3
+
+COUNT = 38
+KEY = fffffffffe00000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 12ad98cbf725137d6a8108c2bed99322
+
+COUNT = 39
+KEY = ffffffffff00000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6afaa996226198b3e2610413ce1b3f78
+
+COUNT = 40
+KEY = ffffffffff80000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2a8ce6747a7e39367828e290848502d9
+
+COUNT = 41
+KEY = ffffffffffc0000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 223736e8b8f89ca1e37b6deab40facf1
+
+COUNT = 42
+KEY = ffffffffffe0000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c0f797e50418b95fa6013333917a9480
+
+COUNT = 43
+KEY = fffffffffff0000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a758de37c2ece2a02c73c01fedc9a132
+
+COUNT = 44
+KEY = fffffffffff8000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3a9b87ae77bae706803966c66c73adbd
+
+COUNT = 45
+KEY = fffffffffffc000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d365ab8df8ffd782e358121a4a4fc541
+
+COUNT = 46
+KEY = fffffffffffe000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c8dcd9e6f75e6c36c8daee0466f0ed74
+
+COUNT = 47
+KEY = ffffffffffff000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c79a637beb1c0304f14014c037e736dd
+
+COUNT = 48
+KEY = ffffffffffff800000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 105f0a25e84ac930d996281a5f954dd9
+
+COUNT = 49
+KEY = ffffffffffffc00000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 42e4074b2927973e8d17ffa92f7fe615
+
+COUNT = 50
+KEY = ffffffffffffe00000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4fe2a9d2c1824449c69e3e0398f12963
+
+COUNT = 51
+KEY = fffffffffffff00000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b7f29c1e1f62847a15253b28a1e9d712
+
+COUNT = 52
+KEY = fffffffffffff80000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 36ed5d29b903f31e8983ef8b0a2bf990
+
+COUNT = 53
+KEY = fffffffffffffc0000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 27b8070270810f9d023f9dd7ff3b4aa2
+
+COUNT = 54
+KEY = fffffffffffffe0000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 94d46e155c1228f61d1a0db4815ecc4b
+
+COUNT = 55
+KEY = ffffffffffffff0000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ca6108d1d98071428eeceef1714b96dd
+
+COUNT = 56
+KEY = ffffffffffffff8000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = dc5b25b71b6296cf73dd2cdcac2f70b1
+
+COUNT = 57
+KEY = ffffffffffffffc000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 44aba95e8a06a2d9d3530d2677878c80
+
+COUNT = 58
+KEY = ffffffffffffffe000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a570d20e89b467e8f5176061b81dd396
+
+COUNT = 59
+KEY = fffffffffffffff000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 758f4467a5d8f1e7307dc30b34e404f4
+
+COUNT = 60
+KEY = fffffffffffffff800000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bcea28e9071b5a2302970ff352451bc5
+
+COUNT = 61
+KEY = fffffffffffffffc00000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7523c00bc177d331ad312e09c9015c1c
+
+COUNT = 62
+KEY = fffffffffffffffe00000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ccac61e3183747b3f5836da21a1bc4f4
+
+COUNT = 63
+KEY = ffffffffffffffff00000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 707b075791878880b44189d3522b8c30
+
+COUNT = 64
+KEY = ffffffffffffffff80000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7132d0c0e4a07593cf12ebb12be7688c
+
+COUNT = 65
+KEY = ffffffffffffffffc0000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = effbac1644deb0c784275fe56e19ead3
+
+COUNT = 66
+KEY = ffffffffffffffffe0000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a005063f30f4228b374e2459738f26bb
+
+COUNT = 67
+KEY = fffffffffffffffff0000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 29975b5f48bb68fcbbc7cea93b452ed7
+
+COUNT = 68
+KEY = fffffffffffffffff8000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cf3f2576e2afedc74bb1ca7eeec1c0e7
+
+COUNT = 69
+KEY = fffffffffffffffffc000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 07c403f5f966e0e3d9f296d6226dca28
+
+COUNT = 70
+KEY = fffffffffffffffffe000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c8c20908249ab4a34d6dd0a31327ff1a
+
+COUNT = 71
+KEY = ffffffffffffffffff000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c0541329ecb6159ab23b7fc5e6a21bca
+
+COUNT = 72
+KEY = ffffffffffffffffff800000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7aa1acf1a2ed9ba72bc6deb31d88b863
+
+COUNT = 73
+KEY = ffffffffffffffffffc00000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 808bd8eddabb6f3bf0d5a8a27be1fe8a
+
+COUNT = 74
+KEY = ffffffffffffffffffe00000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 273c7d7685e14ec66bbb96b8f05b6ddd
+
+COUNT = 75
+KEY = fffffffffffffffffff00000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 32752eefc8c2a93f91b6e73eb07cca6e
+
+COUNT = 76
+KEY = fffffffffffffffffff80000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d893e7d62f6ce502c64f75e281f9c000
+
+COUNT = 77
+KEY = fffffffffffffffffffc0000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8dfd999be5d0cfa35732c0ddc88ff5a5
+
+COUNT = 78
+KEY = fffffffffffffffffffe0000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 02647c76a300c3173b841487eb2bae9f
+
+COUNT = 79
+KEY = ffffffffffffffffffff0000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 172df8b02f04b53adab028b4e01acd87
+
+COUNT = 80
+KEY = ffffffffffffffffffff8000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 054b3bf4998aeb05afd87ec536533a36
+
+COUNT = 81
+KEY = ffffffffffffffffffffc000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3783f7bf44c97f065258a666cae03020
+
+COUNT = 82
+KEY = ffffffffffffffffffffe000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = aad4c8a63f80954104de7b92cede1be1
+
+COUNT = 83
+KEY = fffffffffffffffffffff000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cbfe61810fd5467ccdacb75800f3ac07
+
+COUNT = 84
+KEY = fffffffffffffffffffff800000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 830d8a2590f7d8e1b55a737f4af45f34
+
+COUNT = 85
+KEY = fffffffffffffffffffffc00000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fffcd4683f858058e74314671d43fa2c
+
+COUNT = 86
+KEY = fffffffffffffffffffffe00000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 523d0babbb82f46ebc9e70b1cd41ddd0
+
+COUNT = 87
+KEY = ffffffffffffffffffffff00000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 344aab37080d7486f7d542a309e53eed
+
+COUNT = 88
+KEY = ffffffffffffffffffffff80000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 56c5609d0906b23ab9caca816f5dbebd
+
+COUNT = 89
+KEY = ffffffffffffffffffffffc0000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7026026eedd91adc6d831cdf9894bdc6
+
+COUNT = 90
+KEY = ffffffffffffffffffffffe0000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 88330baa4f2b618fc9d9b021bf503d5a
+
+COUNT = 91
+KEY = fffffffffffffffffffffff0000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fc9e0ea22480b0bac935c8a8ebefcdcf
+
+COUNT = 92
+KEY = fffffffffffffffffffffff8000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 29ca779f398fb04f867da7e8a44756cb
+
+COUNT = 93
+KEY = fffffffffffffffffffffffc000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 51f89c42985786bfc43c6df8ada36832
+
+COUNT = 94
+KEY = fffffffffffffffffffffffe000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6ac1de5fb8f21d874e91c53b560c50e3
+
+COUNT = 95
+KEY = ffffffffffffffffffffffff000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 03aa9058490eda306001a8a9f48d0ca7
+
+COUNT = 96
+KEY = ffffffffffffffffffffffff800000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e34ec71d6128d4871865d617c30b37e3
+
+COUNT = 97
+KEY = ffffffffffffffffffffffffc00000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 14be1c535b17cabd0c4d93529d69bf47
+
+COUNT = 98
+KEY = ffffffffffffffffffffffffe00000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c9ef67756507beec9dd3862883478044
+
+COUNT = 99
+KEY = fffffffffffffffffffffffff00000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 40e231fa5a5948ce2134e92fc0664d4b
+
+COUNT = 100
+KEY = fffffffffffffffffffffffff80000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 03194b8e5dda5530d0c678c0b48f5d92
+
+COUNT = 101
+KEY = fffffffffffffffffffffffffc0000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 90bd086f237cc4fd99f4d76bde6b4826
+
+COUNT = 102
+KEY = fffffffffffffffffffffffffe0000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 19259761ca17130d6ed86d57cd7951ee
+
+COUNT = 103
+KEY = ffffffffffffffffffffffffff0000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d7cbb3f34b9b450f24b0e8518e54da6d
+
+COUNT = 104
+KEY = ffffffffffffffffffffffffff8000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 725b9caebe9f7f417f4068d0d2ee20b3
+
+COUNT = 105
+KEY = ffffffffffffffffffffffffffc000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9d924b934a90ce1fd39b8a9794f82672
+
+COUNT = 106
+KEY = ffffffffffffffffffffffffffe000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c50562bf094526a91c5bc63c0c224995
+
+COUNT = 107
+KEY = fffffffffffffffffffffffffff000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d2f11805046743bd74f57188d9188df7
+
+COUNT = 108
+KEY = fffffffffffffffffffffffffff800000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8dd274bd0f1b58ae345d9e7233f9b8f3
+
+COUNT = 109
+KEY = fffffffffffffffffffffffffffc00000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9d6bdc8f4ce5feb0f3bed2e4b9a9bb0b
+
+COUNT = 110
+KEY = fffffffffffffffffffffffffffe00000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fd5548bcf3f42565f7efa94562528d46
+
+COUNT = 111
+KEY = ffffffffffffffffffffffffffff00000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d2ccaebd3a4c3e80b063748131ba4a71
+
+COUNT = 112
+KEY = ffffffffffffffffffffffffffff80000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e03cb23d9e11c9d93f117e9c0a91b576
+
+COUNT = 113
+KEY = ffffffffffffffffffffffffffffc0000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 78f933a2081ac1db84f69d10f4523fe0
+
+COUNT = 114
+KEY = ffffffffffffffffffffffffffffe0000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4061f7412ed320de0edc8851c2e2436f
+
+COUNT = 115
+KEY = fffffffffffffffffffffffffffff0000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9064ba1cd04ce6bab98474330814b4d4
+
+COUNT = 116
+KEY = fffffffffffffffffffffffffffff8000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 48391bffb9cfff80ac238c886ef0a461
+
+COUNT = 117
+KEY = fffffffffffffffffffffffffffffc000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b8d2a67df5a999fdbf93edd0343296c9
+
+COUNT = 118
+KEY = fffffffffffffffffffffffffffffe000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = aaca7367396b69a221bd632bea386eec
+
+COUNT = 119
+KEY = ffffffffffffffffffffffffffffff000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a80fd5020dfe65f5f16293ec92c6fd89
+
+COUNT = 120
+KEY = ffffffffffffffffffffffffffffff800000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2162995b8217a67f1abc342e146406f8
+
+COUNT = 121
+KEY = ffffffffffffffffffffffffffffffc00000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c6a6164b7a60bae4e986ffac28dfadd9
+
+COUNT = 122
+KEY = ffffffffffffffffffffffffffffffe00000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 64e0d7f900e3d9c83e4b8f96717b2146
+
+COUNT = 123
+KEY = fffffffffffffffffffffffffffffff00000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1ad2561de8c1232f5d8dbab4739b6cbb
+
+COUNT = 124
+KEY = fffffffffffffffffffffffffffffff80000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 279689e9a557f58b1c3bf40c97a90964
+
+COUNT = 125
+KEY = fffffffffffffffffffffffffffffffc0000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c4637e4a5e6377f9cc5a8638045de029
+
+COUNT = 126
+KEY = fffffffffffffffffffffffffffffffe0000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 492e607e5aea4688594b45f3aee3df90
+
+COUNT = 127
+KEY = ffffffffffffffffffffffffffffffff0000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e8c4e4381feec74054954c05b777a00a
+
+COUNT = 128
+KEY = ffffffffffffffffffffffffffffffff8000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 91549514605f38246c9b724ad839f01d
+
+COUNT = 129
+KEY = ffffffffffffffffffffffffffffffffc000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 74b24e3b6fefe40a4f9ef7ac6e44d76a
+
+COUNT = 130
+KEY = ffffffffffffffffffffffffffffffffe000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2437a683dc5d4b52abb4a123a8df86c6
+
+COUNT = 131
+KEY = fffffffffffffffffffffffffffffffff000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bb2852c891c5947d2ed44032c421b85f
+
+COUNT = 132
+KEY = fffffffffffffffffffffffffffffffff800000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1b9f5fbd5e8a4264c0a85b80409afa5e
+
+COUNT = 133
+KEY = fffffffffffffffffffffffffffffffffc00000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 30dab809f85a917fe924733f424ac589
+
+COUNT = 134
+KEY = fffffffffffffffffffffffffffffffffe00000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = eaef5c1f8d605192646695ceadc65f32
+
+COUNT = 135
+KEY = ffffffffffffffffffffffffffffffffff00000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b8aa90040b4c15a12316b78e0f9586fc
+
+COUNT = 136
+KEY = ffffffffffffffffffffffffffffffffff80000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 97fac8297ceaabc87d454350601e0673
+
+COUNT = 137
+KEY = ffffffffffffffffffffffffffffffffffc0000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9b47ef567ac28dfe488492f157e2b2e0
+
+COUNT = 138
+KEY = ffffffffffffffffffffffffffffffffffe0000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1b8426027ddb962b5c5ba7eb8bc9ab63
+
+COUNT = 139
+KEY = fffffffffffffffffffffffffffffffffff0000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e917fc77e71992a12dbe4c18068bec82
+
+COUNT = 140
+KEY = fffffffffffffffffffffffffffffffffff8000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = dceebbc98840f8ae6daf76573b7e56f4
+
+COUNT = 141
+KEY = fffffffffffffffffffffffffffffffffffc000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4e11a9f74205125b61e0aee047eca20d
+
+COUNT = 142
+KEY = fffffffffffffffffffffffffffffffffffe000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f60467f55a1f17eab88e800120cbc284
+
+COUNT = 143
+KEY = ffffffffffffffffffffffffffffffffffff000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d436649f600b449ee276530f0cd83c11
+
+COUNT = 144
+KEY = ffffffffffffffffffffffffffffffffffff800000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3bc0e3656a9e3ac7cd378a737f53b637
+
+COUNT = 145
+KEY = ffffffffffffffffffffffffffffffffffffc00000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6bacae63d33b928aa8380f8d54d88c17
+
+COUNT = 146
+KEY = ffffffffffffffffffffffffffffffffffffe00000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8935ffbc75ae6251bf8e859f085adcb9
+
+COUNT = 147
+KEY = fffffffffffffffffffffffffffffffffffff00000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 93dc4970fe35f67747cb0562c06d875a
+
+COUNT = 148
+KEY = fffffffffffffffffffffffffffffffffffff80000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 14f9df858975851797ba604fb0d16cc7
+
+COUNT = 149
+KEY = fffffffffffffffffffffffffffffffffffffc0000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 02ea0c98dca10b38c21b3b14e8d1b71f
+
+COUNT = 150
+KEY = fffffffffffffffffffffffffffffffffffffe0000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8f091b1b5b0749b2adc803e63dda9b72
+
+COUNT = 151
+KEY = ffffffffffffffffffffffffffffffffffffff0000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 05b389e3322c6da08384345a4137fd08
+
+COUNT = 152
+KEY = ffffffffffffffffffffffffffffffffffffff8000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 381308c438f35b399f10ad71b05027d8
+
+COUNT = 153
+KEY = ffffffffffffffffffffffffffffffffffffffc000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 68c230fcfa9279c3409fc423e2acbe04
+
+COUNT = 154
+KEY = ffffffffffffffffffffffffffffffffffffffe000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1c84a475acb011f3f59f4f46b76274c0
+
+COUNT = 155
+KEY = fffffffffffffffffffffffffffffffffffffff000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 45119b68cb3f8399ee60066b5611a4d7
+
+COUNT = 156
+KEY = fffffffffffffffffffffffffffffffffffffff800000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9423762f527a4060ffca312dcca22a16
+
+COUNT = 157
+KEY = fffffffffffffffffffffffffffffffffffffffc00000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f361a2745a33f056a5ac6ace2f08e344
+
+COUNT = 158
+KEY = fffffffffffffffffffffffffffffffffffffffe00000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5ef145766eca849f5d011536a6557fdb
+
+COUNT = 159
+KEY = ffffffffffffffffffffffffffffffffffffffff00000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c9af27b2c89c9b4cf4a0c4106ac80318
+
+COUNT = 160
+KEY = ffffffffffffffffffffffffffffffffffffffff80000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fb9c4f16c621f4eab7e9ac1d7551dd57
+
+COUNT = 161
+KEY = ffffffffffffffffffffffffffffffffffffffffc0000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 138e06fba466fa70854d8c2e524cffb2
+
+COUNT = 162
+KEY = ffffffffffffffffffffffffffffffffffffffffe0000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fb4bc78b225070773f04c40466d4e90c
+
+COUNT = 163
+KEY = fffffffffffffffffffffffffffffffffffffffff0000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8b2cbff1ed0150feda8a4799be94551f
+
+COUNT = 164
+KEY = fffffffffffffffffffffffffffffffffffffffff8000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 08b30d7b3f27962709a36bcadfb974bd
+
+COUNT = 165
+KEY = fffffffffffffffffffffffffffffffffffffffffc000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fdf6d32e044d77adcf37fb97ac213326
+
+COUNT = 166
+KEY = fffffffffffffffffffffffffffffffffffffffffe000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 93cb284ecdcfd781a8afe32077949e88
+
+COUNT = 167
+KEY = ffffffffffffffffffffffffffffffffffffffffff000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7b017bb02ec87b2b94c96e40a26fc71a
+
+COUNT = 168
+KEY = ffffffffffffffffffffffffffffffffffffffffff800000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c5c038b6990664ab08a3aaa5df9f3266
+
+COUNT = 169
+KEY = ffffffffffffffffffffffffffffffffffffffffffc00000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4b7020be37fab6259b2a27f4ec551576
+
+COUNT = 170
+KEY = ffffffffffffffffffffffffffffffffffffffffffe00000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 60136703374f64e860b48ce31f930716
+
+COUNT = 171
+KEY = fffffffffffffffffffffffffffffffffffffffffff00000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8d63a269b14d506ccc401ab8a9f1b591
+
+COUNT = 172
+KEY = fffffffffffffffffffffffffffffffffffffffffff80000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d317f81dc6aa454aee4bd4a5a5cff4bd
+
+COUNT = 173
+KEY = fffffffffffffffffffffffffffffffffffffffffffc0000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = dddececd5354f04d530d76ed884246eb
+
+COUNT = 174
+KEY = fffffffffffffffffffffffffffffffffffffffffffe0000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 41c5205cc8fd8eda9a3cffd2518f365a
+
+COUNT = 175
+KEY = ffffffffffffffffffffffffffffffffffffffffffff0000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cf42fb474293d96eca9db1b37b1ba676
+
+COUNT = 176
+KEY = ffffffffffffffffffffffffffffffffffffffffffff8000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a231692607169b4ecdead5cd3b10db3e
+
+COUNT = 177
+KEY = ffffffffffffffffffffffffffffffffffffffffffffc000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ace4b91c9c669e77e7acacd19859ed49
+
+COUNT = 178
+KEY = ffffffffffffffffffffffffffffffffffffffffffffe000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 75db7cfd4a7b2b62ab78a48f3ddaf4af
+
+COUNT = 179
+KEY = fffffffffffffffffffffffffffffffffffffffffffff000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c1faba2d46e259cf480d7c38e4572a58
+
+COUNT = 180
+KEY = fffffffffffffffffffffffffffffffffffffffffffff800
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 241c45bc6ae16dee6eb7bea128701582
+
+COUNT = 181
+KEY = fffffffffffffffffffffffffffffffffffffffffffffc00
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8fd03057cf1364420c2b78069a3e2502
+
+COUNT = 182
+KEY = fffffffffffffffffffffffffffffffffffffffffffffe00
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ddb505e6cc1384cbaec1df90b80beb20
+
+COUNT = 183
+KEY = ffffffffffffffffffffffffffffffffffffffffffffff00
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5674a3bed27bf4bd3622f9f5fe208306
+
+COUNT = 184
+KEY = ffffffffffffffffffffffffffffffffffffffffffffff80
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b687f26a89cfbfbb8e5eeac54055315e
+
+COUNT = 185
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffc0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 0547dd32d3b29ab6a4caeb606c5b6f78
+
+COUNT = 186
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffe0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 186861f8bc5386d31fb77f720c3226e6
+
+COUNT = 187
+KEY = fffffffffffffffffffffffffffffffffffffffffffffff0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = eacf1e6c4224efb38900b185ab1dfd42
+
+COUNT = 188
+KEY = fffffffffffffffffffffffffffffffffffffffffffffff8
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d241aab05a42d319de81d874f5c7b90d
+
+COUNT = 189
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffc
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5eb9bc759e2ad8d2140a6c762ae9e1ab
+
+COUNT = 190
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffe
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 018596e15e78e2c064159defce5f3085
+
+COUNT = 191
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffff
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = dd8a493514231cbf56eccee4c40889fb
+
+
+ECB Varying Plaintext 256 bits
+
+COUNT = 0
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 80000000000000000000000000000000
+CIPHERTEXT = ddc6bf790c15760d8d9aeb6f9a75fd4e
+
+COUNT = 1
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = c0000000000000000000000000000000
+CIPHERTEXT = 0a6bdc6d4c1e6280301fd8e97ddbe601
+
+COUNT = 2
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = e0000000000000000000000000000000
+CIPHERTEXT = 9b80eefb7ebe2d2b16247aa0efc72f5d
+
+COUNT = 3
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = f0000000000000000000000000000000
+CIPHERTEXT = 7f2c5ece07a98d8bee13c51177395ff7
+
+COUNT = 4
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = f8000000000000000000000000000000
+CIPHERTEXT = 7818d800dcf6f4be1e0e94f403d1e4c2
+
+COUNT = 5
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fc000000000000000000000000000000
+CIPHERTEXT = e74cd1c92f0919c35a0324123d6177d3
+
+COUNT = 6
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fe000000000000000000000000000000
+CIPHERTEXT = 8092a4dcf2da7e77e93bdd371dfed82e
+
+COUNT = 7
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ff000000000000000000000000000000
+CIPHERTEXT = 49af6b372135acef10132e548f217b17
+
+COUNT = 8
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ff800000000000000000000000000000
+CIPHERTEXT = 8bcd40f94ebb63b9f7909676e667f1e7
+
+COUNT = 9
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffc00000000000000000000000000000
+CIPHERTEXT = fe1cffb83f45dcfb38b29be438dbd3ab
+
+COUNT = 10
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffe00000000000000000000000000000
+CIPHERTEXT = 0dc58a8d886623705aec15cb1e70dc0e
+
+COUNT = 11
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fff00000000000000000000000000000
+CIPHERTEXT = c218faa16056bd0774c3e8d79c35a5e4
+
+COUNT = 12
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fff80000000000000000000000000000
+CIPHERTEXT = 047bba83f7aa841731504e012208fc9e
+
+COUNT = 13
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffc0000000000000000000000000000
+CIPHERTEXT = dc8f0e4915fd81ba70a331310882f6da
+
+COUNT = 14
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffe0000000000000000000000000000
+CIPHERTEXT = 1569859ea6b7206c30bf4fd0cbfac33c
+
+COUNT = 15
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffff0000000000000000000000000000
+CIPHERTEXT = 300ade92f88f48fa2df730ec16ef44cd
+
+COUNT = 16
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffff8000000000000000000000000000
+CIPHERTEXT = 1fe6cc3c05965dc08eb0590c95ac71d0
+
+COUNT = 17
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffc000000000000000000000000000
+CIPHERTEXT = 59e858eaaa97fec38111275b6cf5abc0
+
+COUNT = 18
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffe000000000000000000000000000
+CIPHERTEXT = 2239455e7afe3b0616100288cc5a723b
+
+COUNT = 19
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffff000000000000000000000000000
+CIPHERTEXT = 3ee500c5c8d63479717163e55c5c4522
+
+COUNT = 20
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffff800000000000000000000000000
+CIPHERTEXT = d5e38bf15f16d90e3e214041d774daa8
+
+COUNT = 21
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffc00000000000000000000000000
+CIPHERTEXT = b1f4066e6f4f187dfe5f2ad1b17819d0
+
+COUNT = 22
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffe00000000000000000000000000
+CIPHERTEXT = 6ef4cc4de49b11065d7af2909854794a
+
+COUNT = 23
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffff00000000000000000000000000
+CIPHERTEXT = ac86bc606b6640c309e782f232bf367f
+
+COUNT = 24
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffff80000000000000000000000000
+CIPHERTEXT = 36aff0ef7bf3280772cf4cac80a0d2b2
+
+COUNT = 25
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffc0000000000000000000000000
+CIPHERTEXT = 1f8eedea0f62a1406d58cfc3ecea72cf
+
+COUNT = 26
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffe0000000000000000000000000
+CIPHERTEXT = abf4154a3375a1d3e6b1d454438f95a6
+
+COUNT = 27
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffff0000000000000000000000000
+CIPHERTEXT = 96f96e9d607f6615fc192061ee648b07
+
+COUNT = 28
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffff8000000000000000000000000
+CIPHERTEXT = cf37cdaaa0d2d536c71857634c792064
+
+COUNT = 29
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffc000000000000000000000000
+CIPHERTEXT = fbd6640c80245c2b805373f130703127
+
+COUNT = 30
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffe000000000000000000000000
+CIPHERTEXT = 8d6a8afe55a6e481badae0d146f436db
+
+COUNT = 31
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffff000000000000000000000000
+CIPHERTEXT = 6a4981f2915e3e68af6c22385dd06756
+
+COUNT = 32
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffff800000000000000000000000
+CIPHERTEXT = 42a1136e5f8d8d21d3101998642d573b
+
+COUNT = 33
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffc00000000000000000000000
+CIPHERTEXT = 9b471596dc69ae1586cee6158b0b0181
+
+COUNT = 34
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffe00000000000000000000000
+CIPHERTEXT = 753665c4af1eff33aa8b628bf8741cfd
+
+COUNT = 35
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffff00000000000000000000000
+CIPHERTEXT = 9a682acf40be01f5b2a4193c9a82404d
+
+COUNT = 36
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffff80000000000000000000000
+CIPHERTEXT = 54fafe26e4287f17d1935f87eb9ade01
+
+COUNT = 37
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffc0000000000000000000000
+CIPHERTEXT = 49d541b2e74cfe73e6a8e8225f7bd449
+
+COUNT = 38
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffe0000000000000000000000
+CIPHERTEXT = 11a45530f624ff6f76a1b3826626ff7b
+
+COUNT = 39
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffff0000000000000000000000
+CIPHERTEXT = f96b0c4a8bc6c86130289f60b43b8fba
+
+COUNT = 40
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffff8000000000000000000000
+CIPHERTEXT = 48c7d0e80834ebdc35b6735f76b46c8b
+
+COUNT = 41
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffc000000000000000000000
+CIPHERTEXT = 2463531ab54d66955e73edc4cb8eaa45
+
+COUNT = 42
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffe000000000000000000000
+CIPHERTEXT = ac9bd8e2530469134b9d5b065d4f565b
+
+COUNT = 43
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffff000000000000000000000
+CIPHERTEXT = 3f5f9106d0e52f973d4890e6f37e8a00
+
+COUNT = 44
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffff800000000000000000000
+CIPHERTEXT = 20ebc86f1304d272e2e207e59db639f0
+
+COUNT = 45
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffc00000000000000000000
+CIPHERTEXT = e67ae6426bf9526c972cff072b52252c
+
+COUNT = 46
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffe00000000000000000000
+CIPHERTEXT = 1a518dddaf9efa0d002cc58d107edfc8
+
+COUNT = 47
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffff00000000000000000000
+CIPHERTEXT = ead731af4d3a2fe3b34bed047942a49f
+
+COUNT = 48
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffff80000000000000000000
+CIPHERTEXT = b1d4efe40242f83e93b6c8d7efb5eae9
+
+COUNT = 49
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffc0000000000000000000
+CIPHERTEXT = cd2b1fec11fd906c5c7630099443610a
+
+COUNT = 50
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffe0000000000000000000
+CIPHERTEXT = a1853fe47fe29289d153161d06387d21
+
+COUNT = 51
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffff0000000000000000000
+CIPHERTEXT = 4632154179a555c17ea604d0889fab14
+
+COUNT = 52
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffff8000000000000000000
+CIPHERTEXT = dd27cac6401a022e8f38f9f93e774417
+
+COUNT = 53
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffc000000000000000000
+CIPHERTEXT = c090313eb98674f35f3123385fb95d4d
+
+COUNT = 54
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffe000000000000000000
+CIPHERTEXT = cc3526262b92f02edce548f716b9f45c
+
+COUNT = 55
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffff000000000000000000
+CIPHERTEXT = c0838d1a2b16a7c7f0dfcc433c399c33
+
+COUNT = 56
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffff800000000000000000
+CIPHERTEXT = 0d9ac756eb297695eed4d382eb126d26
+
+COUNT = 57
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffc00000000000000000
+CIPHERTEXT = 56ede9dda3f6f141bff1757fa689c3e1
+
+COUNT = 58
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffe00000000000000000
+CIPHERTEXT = 768f520efe0f23e61d3ec8ad9ce91774
+
+COUNT = 59
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffff00000000000000000
+CIPHERTEXT = b1144ddfa75755213390e7c596660490
+
+COUNT = 60
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffff80000000000000000
+CIPHERTEXT = 1d7c0c4040b355b9d107a99325e3b050
+
+COUNT = 61
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffc0000000000000000
+CIPHERTEXT = d8e2bb1ae8ee3dcf5bf7d6c38da82a1a
+
+COUNT = 62
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffe0000000000000000
+CIPHERTEXT = faf82d178af25a9886a47e7f789b98d7
+
+COUNT = 63
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffff0000000000000000
+CIPHERTEXT = 9b58dbfd77fe5aca9cfc190cd1b82d19
+
+COUNT = 64
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffff8000000000000000
+CIPHERTEXT = 77f392089042e478ac16c0c86a0b5db5
+
+COUNT = 65
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffc000000000000000
+CIPHERTEXT = 19f08e3420ee69b477ca1420281c4782
+
+COUNT = 66
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffe000000000000000
+CIPHERTEXT = a1b19beee4e117139f74b3c53fdcb875
+
+COUNT = 67
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffff000000000000000
+CIPHERTEXT = a37a5869b218a9f3a0868d19aea0ad6a
+
+COUNT = 68
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffff800000000000000
+CIPHERTEXT = bc3594e865bcd0261b13202731f33580
+
+COUNT = 69
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffc00000000000000
+CIPHERTEXT = 811441ce1d309eee7185e8c752c07557
+
+COUNT = 70
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffe00000000000000
+CIPHERTEXT = 959971ce4134190563518e700b9874d1
+
+COUNT = 71
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffff00000000000000
+CIPHERTEXT = 76b5614a042707c98e2132e2e805fe63
+
+COUNT = 72
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffff80000000000000
+CIPHERTEXT = 7d9fa6a57530d0f036fec31c230b0cc6
+
+COUNT = 73
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffc0000000000000
+CIPHERTEXT = 964153a83bf6989a4ba80daa91c3e081
+
+COUNT = 74
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffe0000000000000
+CIPHERTEXT = a013014d4ce8054cf2591d06f6f2f176
+
+COUNT = 75
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffff0000000000000
+CIPHERTEXT = d1c5f6399bf382502e385eee1474a869
+
+COUNT = 76
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffff8000000000000
+CIPHERTEXT = 0007e20b8298ec354f0f5fe7470f36bd
+
+COUNT = 77
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffc000000000000
+CIPHERTEXT = b95ba05b332da61ef63a2b31fcad9879
+
+COUNT = 78
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffe000000000000
+CIPHERTEXT = 4620a49bd967491561669ab25dce45f4
+
+COUNT = 79
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffff000000000000
+CIPHERTEXT = 12e71214ae8e04f0bb63d7425c6f14d5
+
+COUNT = 80
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffff800000000000
+CIPHERTEXT = 4cc42fc1407b008fe350907c092e80ac
+
+COUNT = 81
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffc00000000000
+CIPHERTEXT = 08b244ce7cbc8ee97fbba808cb146fda
+
+COUNT = 82
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffe00000000000
+CIPHERTEXT = 39b333e8694f21546ad1edd9d87ed95b
+
+COUNT = 83
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffff00000000000
+CIPHERTEXT = 3b271f8ab2e6e4a20ba8090f43ba78f3
+
+COUNT = 84
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffff80000000000
+CIPHERTEXT = 9ad983f3bf651cd0393f0a73cccdea50
+
+COUNT = 85
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffc0000000000
+CIPHERTEXT = 8f476cbff75c1f725ce18e4bbcd19b32
+
+COUNT = 86
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffe0000000000
+CIPHERTEXT = 905b6267f1d6ab5320835a133f096f2a
+
+COUNT = 87
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffff0000000000
+CIPHERTEXT = 145b60d6d0193c23f4221848a892d61a
+
+COUNT = 88
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffff8000000000
+CIPHERTEXT = 55cfb3fb6d75cad0445bbc8dafa25b0f
+
+COUNT = 89
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffc000000000
+CIPHERTEXT = 7b8e7098e357ef71237d46d8b075b0f5
+
+COUNT = 90
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffe000000000
+CIPHERTEXT = 2bf27229901eb40f2df9d8398d1505ae
+
+COUNT = 91
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffff000000000
+CIPHERTEXT = 83a63402a77f9ad5c1e931a931ecd706
+
+COUNT = 92
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffff800000000
+CIPHERTEXT = 6f8ba6521152d31f2bada1843e26b973
+
+COUNT = 93
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffc00000000
+CIPHERTEXT = e5c3b8e30fd2d8e6239b17b44bd23bbd
+
+COUNT = 94
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffe00000000
+CIPHERTEXT = 1ac1f7102c59933e8b2ddc3f14e94baa
+
+COUNT = 95
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffff00000000
+CIPHERTEXT = 21d9ba49f276b45f11af8fc71a088e3d
+
+COUNT = 96
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffff80000000
+CIPHERTEXT = 649f1cddc3792b4638635a392bc9bade
+
+COUNT = 97
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffc0000000
+CIPHERTEXT = e2775e4b59c1bc2e31a2078c11b5a08c
+
+COUNT = 98
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffe0000000
+CIPHERTEXT = 2be1fae5048a25582a679ca10905eb80
+
+COUNT = 99
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffff0000000
+CIPHERTEXT = da86f292c6f41ea34fb2068df75ecc29
+
+COUNT = 100
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffff8000000
+CIPHERTEXT = 220df19f85d69b1b562fa69a3c5beca5
+
+COUNT = 101
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffc000000
+CIPHERTEXT = 1f11d5d0355e0b556ccdb6c7f5083b4d
+
+COUNT = 102
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffe000000
+CIPHERTEXT = 62526b78be79cb384633c91f83b4151b
+
+COUNT = 103
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffff000000
+CIPHERTEXT = 90ddbcb950843592dd47bbef00fdc876
+
+COUNT = 104
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffff800000
+CIPHERTEXT = 2fd0e41c5b8402277354a7391d2618e2
+
+COUNT = 105
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffc00000
+CIPHERTEXT = 3cdf13e72dee4c581bafec70b85f9660
+
+COUNT = 106
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffe00000
+CIPHERTEXT = afa2ffc137577092e2b654fa199d2c43
+
+COUNT = 107
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffff00000
+CIPHERTEXT = 8d683ee63e60d208e343ce48dbc44cac
+
+COUNT = 108
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffff80000
+CIPHERTEXT = 705a4ef8ba2133729c20185c3d3a4763
+
+COUNT = 109
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffc0000
+CIPHERTEXT = 0861a861c3db4e94194211b77ed761b9
+
+COUNT = 110
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffe0000
+CIPHERTEXT = 4b00c27e8b26da7eab9d3a88dec8b031
+
+COUNT = 111
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffff0000
+CIPHERTEXT = 5f397bf03084820cc8810d52e5b666e9
+
+COUNT = 112
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffff8000
+CIPHERTEXT = 63fafabb72c07bfbd3ddc9b1203104b8
+
+COUNT = 113
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffc000
+CIPHERTEXT = 683e2140585b18452dd4ffbb93c95df9
+
+COUNT = 114
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffe000
+CIPHERTEXT = 286894e48e537f8763b56707d7d155c8
+
+COUNT = 115
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffff000
+CIPHERTEXT = a423deabc173dcf7e2c4c53e77d37cd1
+
+COUNT = 116
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffff800
+CIPHERTEXT = eb8168313e1cfdfdb5e986d5429cf172
+
+COUNT = 117
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffc00
+CIPHERTEXT = 27127daafc9accd2fb334ec3eba52323
+
+COUNT = 118
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffe00
+CIPHERTEXT = ee0715b96f72e3f7a22a5064fc592f4c
+
+COUNT = 119
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffff00
+CIPHERTEXT = 29ee526770f2a11dcfa989d1ce88830f
+
+COUNT = 120
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffff80
+CIPHERTEXT = 0493370e054b09871130fe49af730a5a
+
+COUNT = 121
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffffc0
+CIPHERTEXT = 9b7b940f6c509f9e44a4ee140448ee46
+
+COUNT = 122
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffffe0
+CIPHERTEXT = 2915be4a1ecfdcbe3e023811a12bb6c7
+
+COUNT = 123
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffff0
+CIPHERTEXT = 7240e524bc51d8c4d440b1be55d1062c
+
+COUNT = 124
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffff8
+CIPHERTEXT = da63039d38cb4612b2dc36ba26684b93
+
+COUNT = 125
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffffc
+CIPHERTEXT = 0f59cb5a4b522e2ac56c1a64f558ad9a
+
+COUNT = 126
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = fffffffffffffffffffffffffffffffe
+CIPHERTEXT = 7bfe9d876c6d63c1d035da8fe21c409d
+
+COUNT = 127
+KEY = 0000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = ffffffffffffffffffffffffffffffff
+CIPHERTEXT = acdace8078a32b1a182bfa4987ca1347
+
+
+ECB Varying Key 256 bits
+
+COUNT = 0
+KEY = 8000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e35a6dcb19b201a01ebcfa8aa22b5759
+
+COUNT = 1
+KEY = c000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b29169cdcf2d83e838125a12ee6aa400
+
+COUNT = 2
+KEY = e000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d8f3a72fc3cdf74dfaf6c3e6b97b2fa6
+
+COUNT = 3
+KEY = f000000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1c777679d50037c79491a94da76a9a35
+
+COUNT = 4
+KEY = f800000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9cf4893ecafa0a0247a898e040691559
+
+COUNT = 5
+KEY = fc00000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8fbb413703735326310a269bd3aa94b2
+
+COUNT = 6
+KEY = fe00000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 60e32246bed2b0e859e55c1cc6b26502
+
+COUNT = 7
+KEY = ff00000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ec52a212f80a09df6317021bc2a9819e
+
+COUNT = 8
+KEY = ff80000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f23e5b600eb70dbccf6c0b1d9a68182c
+
+COUNT = 9
+KEY = ffc0000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a3f599d63a82a968c33fe26590745970
+
+COUNT = 10
+KEY = ffe0000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d1ccb9b1337002cbac42c520b5d67722
+
+COUNT = 11
+KEY = fff0000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cc111f6c37cf40a1159d00fb59fb0488
+
+COUNT = 12
+KEY = fff8000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = dc43b51ab609052372989a26e9cdd714
+
+COUNT = 13
+KEY = fffc000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4dcede8da9e2578f39703d4433dc6459
+
+COUNT = 14
+KEY = fffe000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1a4c1c263bbccfafc11782894685e3a8
+
+COUNT = 15
+KEY = ffff000000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 937ad84880db50613423d6d527a2823d
+
+COUNT = 16
+KEY = ffff800000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 610b71dfc688e150d8152c5b35ebc14d
+
+COUNT = 17
+KEY = ffffc00000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 27ef2495dabf323885aab39c80f18d8b
+
+COUNT = 18
+KEY = ffffe00000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 633cafea395bc03adae3a1e2068e4b4e
+
+COUNT = 19
+KEY = fffff00000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6e1b482b53761cf631819b749a6f3724
+
+COUNT = 20
+KEY = fffff80000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 976e6f851ab52c771998dbb2d71c75a9
+
+COUNT = 21
+KEY = fffffc0000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 85f2ba84f8c307cf525e124c3e22e6cc
+
+COUNT = 22
+KEY = fffffe0000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6bcca98bf6a835fa64955f72de4115fe
+
+COUNT = 23
+KEY = ffffff0000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2c75e2d36eebd65411f14fd0eb1d2a06
+
+COUNT = 24
+KEY = ffffff8000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bd49295006250ffca5100b6007a0eade
+
+COUNT = 25
+KEY = ffffffc000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a190527d0ef7c70f459cd3940df316ec
+
+COUNT = 26
+KEY = ffffffe000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bbd1097a62433f79449fa97d4ee80dbf
+
+COUNT = 27
+KEY = fffffff000000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 07058e408f5b99b0e0f061a1761b5b3b
+
+COUNT = 28
+KEY = fffffff800000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5fd1f13fa0f31e37fabde328f894eac2
+
+COUNT = 29
+KEY = fffffffc00000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fc4af7c948df26e2ef3e01c1ee5b8f6f
+
+COUNT = 30
+KEY = fffffffe00000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 829fd7208fb92d44a074a677ee9861ac
+
+COUNT = 31
+KEY = ffffffff00000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ad9fc613a703251b54c64a0e76431711
+
+COUNT = 32
+KEY = ffffffff80000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 33ac9eccc4cc75e2711618f80b1548e8
+
+COUNT = 33
+KEY = ffffffffc0000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2025c74b8ad8f4cda17ee2049c4c902d
+
+COUNT = 34
+KEY = ffffffffe0000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f85ca05fe528f1ce9b790166e8d551e7
+
+COUNT = 35
+KEY = fffffffff0000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6f6238d8966048d4967154e0dad5a6c9
+
+COUNT = 36
+KEY = fffffffff8000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f2b21b4e7640a9b3346de8b82fb41e49
+
+COUNT = 37
+KEY = fffffffffc000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f836f251ad1d11d49dc344628b1884e1
+
+COUNT = 38
+KEY = fffffffffe000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 077e9470ae7abea5a9769d49182628c3
+
+COUNT = 39
+KEY = ffffffffff000000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e0dcc2d27fc9865633f85223cf0d611f
+
+COUNT = 40
+KEY = ffffffffff800000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = be66cfea2fecd6bf0ec7b4352c99bcaa
+
+COUNT = 41
+KEY = ffffffffffc00000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = df31144f87a2ef523facdcf21a427804
+
+COUNT = 42
+KEY = ffffffffffe00000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b5bb0f5629fb6aae5e1839a3c3625d63
+
+COUNT = 43
+KEY = fffffffffff00000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3c9db3335306fe1ec612bdbfae6b6028
+
+COUNT = 44
+KEY = fffffffffff80000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3dd5c34634a79d3cfcc8339760e6f5f4
+
+COUNT = 45
+KEY = fffffffffffc0000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 82bda118a3ed7af314fa2ccc5c07b761
+
+COUNT = 46
+KEY = fffffffffffe0000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2937a64f7d4f46fe6fea3b349ec78e38
+
+COUNT = 47
+KEY = ffffffffffff0000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 225f068c28476605735ad671bb8f39f3
+
+COUNT = 48
+KEY = ffffffffffff8000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ae682c5ecd71898e08942ac9aa89875c
+
+COUNT = 49
+KEY = ffffffffffffc000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5e031cb9d676c3022d7f26227e85c38f
+
+COUNT = 50
+KEY = ffffffffffffe000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a78463fb064db5d52bb64bfef64f2dda
+
+COUNT = 51
+KEY = fffffffffffff000000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8aa9b75e784593876c53a00eae5af52b
+
+COUNT = 52
+KEY = fffffffffffff800000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3f84566df23da48af692722fe980573a
+
+COUNT = 53
+KEY = fffffffffffffc00000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 31690b5ed41c7eb42a1e83270a7ff0e6
+
+COUNT = 54
+KEY = fffffffffffffe00000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 77dd7702646d55f08365e477d3590eda
+
+COUNT = 55
+KEY = ffffffffffffff00000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4c022ac62b3cb78d739cc67b3e20bb7e
+
+COUNT = 56
+KEY = ffffffffffffff80000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 092fa137ce18b5dfe7906f550bb13370
+
+COUNT = 57
+KEY = ffffffffffffffc0000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3e0cdadf2e68353c0027672c97144dd3
+
+COUNT = 58
+KEY = ffffffffffffffe0000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d8c4b200b383fc1f2b2ea677618a1d27
+
+COUNT = 59
+KEY = fffffffffffffff0000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 11825f99b0e9bb3477c1c0713b015aac
+
+COUNT = 60
+KEY = fffffffffffffff8000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f8b9fffb5c187f7ddc7ab10f4fb77576
+
+COUNT = 61
+KEY = fffffffffffffffc000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ffb4e87a32b37d6f2c8328d3b5377802
+
+COUNT = 62
+KEY = fffffffffffffffe000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d276c13a5d220f4da9224e74896391ce
+
+COUNT = 63
+KEY = ffffffffffffffff000000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 94efe7a0e2e031e2536da01df799c927
+
+COUNT = 64
+KEY = ffffffffffffffff800000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8f8fd822680a85974e53a5a8eb9d38de
+
+COUNT = 65
+KEY = ffffffffffffffffc00000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e0f0a91b2e45f8cc37b7805a3042588d
+
+COUNT = 66
+KEY = ffffffffffffffffe00000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 597a6252255e46d6364dbeeda31e279c
+
+COUNT = 67
+KEY = fffffffffffffffff00000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f51a0f694442b8f05571797fec7ee8bf
+
+COUNT = 68
+KEY = fffffffffffffffff80000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9ff071b165b5198a93dddeebc54d09b5
+
+COUNT = 69
+KEY = fffffffffffffffffc0000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c20a19fd5758b0c4bc1a5df89cf73877
+
+COUNT = 70
+KEY = fffffffffffffffffe0000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 97120166307119ca2280e9315668e96f
+
+COUNT = 71
+KEY = ffffffffffffffffff0000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4b3b9f1e099c2a09dc091e90e4f18f0a
+
+COUNT = 72
+KEY = ffffffffffffffffff8000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = eb040b891d4b37f6851f7ec219cd3f6d
+
+COUNT = 73
+KEY = ffffffffffffffffffc000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9f0fdec08b7fd79aa39535bea42db92a
+
+COUNT = 74
+KEY = ffffffffffffffffffe000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2e70f168fc74bf911df240bcd2cef236
+
+COUNT = 75
+KEY = fffffffffffffffffff000000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 462ccd7f5fd1108dbc152f3cacad328b
+
+COUNT = 76
+KEY = fffffffffffffffffff800000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a4af534a7d0b643a01868785d86dfb95
+
+COUNT = 77
+KEY = fffffffffffffffffffc00000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ab980296197e1a5022326c31da4bf6f3
+
+COUNT = 78
+KEY = fffffffffffffffffffe00000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f97d57b3333b6281b07d486db2d4e20c
+
+COUNT = 79
+KEY = ffffffffffffffffffff00000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f33fa36720231afe4c759ade6bd62eb6
+
+COUNT = 80
+KEY = ffffffffffffffffffff80000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fdcfac0c02ca538343c68117e0a15938
+
+COUNT = 81
+KEY = ffffffffffffffffffffc0000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ad4916f5ee5772be764fc027b8a6e539
+
+COUNT = 82
+KEY = ffffffffffffffffffffe0000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2e16873e1678610d7e14c02d002ea845
+
+COUNT = 83
+KEY = fffffffffffffffffffff0000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4e6e627c1acc51340053a8236d579576
+
+COUNT = 84
+KEY = fffffffffffffffffffff8000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ab0c8410aeeead92feec1eb430d652cb
+
+COUNT = 85
+KEY = fffffffffffffffffffffc000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e86f7e23e835e114977f60e1a592202e
+
+COUNT = 86
+KEY = fffffffffffffffffffffe000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e68ad5055a367041fade09d9a70a794b
+
+COUNT = 87
+KEY = ffffffffffffffffffffff000000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 0791823a3c666bb6162825e78606a7fe
+
+COUNT = 88
+KEY = ffffffffffffffffffffff800000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = dcca366a9bf47b7b868b77e25c18a364
+
+COUNT = 89
+KEY = ffffffffffffffffffffffc00000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 684c9efc237e4a442965f84bce20247a
+
+COUNT = 90
+KEY = ffffffffffffffffffffffe00000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a858411ffbe63fdb9c8aa1bfaed67b52
+
+COUNT = 91
+KEY = fffffffffffffffffffffff00000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 04bc3da2179c3015498b0e03910db5b8
+
+COUNT = 92
+KEY = fffffffffffffffffffffff80000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 40071eeab3f935dbc25d00841460260f
+
+COUNT = 93
+KEY = fffffffffffffffffffffffc0000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 0ebd7c30ed2016e08ba806ddb008bcc8
+
+COUNT = 94
+KEY = fffffffffffffffffffffffe0000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 15c6becf0f4cec7129cbd22d1a79b1b8
+
+COUNT = 95
+KEY = ffffffffffffffffffffffff0000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 0aeede5b91f721700e9e62edbf60b781
+
+COUNT = 96
+KEY = ffffffffffffffffffffffff8000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 266581af0dcfbed1585e0a242c64b8df
+
+COUNT = 97
+KEY = ffffffffffffffffffffffffc000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6693dc911662ae473216ba22189a511a
+
+COUNT = 98
+KEY = ffffffffffffffffffffffffe000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7606fa36d86473e6fb3a1bb0e2c0adf5
+
+COUNT = 99
+KEY = fffffffffffffffffffffffff000000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 112078e9e11fbb78e26ffb8899e96b9a
+
+COUNT = 100
+KEY = fffffffffffffffffffffffff800000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 40b264e921e9e4a82694589ef3798262
+
+COUNT = 101
+KEY = fffffffffffffffffffffffffc00000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8d4595cb4fa7026715f55bd68e2882f9
+
+COUNT = 102
+KEY = fffffffffffffffffffffffffe00000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b588a302bdbc09197df1edae68926ed9
+
+COUNT = 103
+KEY = ffffffffffffffffffffffffff00000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 33f7502390b8a4a221cfecd0666624ba
+
+COUNT = 104
+KEY = ffffffffffffffffffffffffff80000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3d20253adbce3be2373767c4d822c566
+
+COUNT = 105
+KEY = ffffffffffffffffffffffffffc0000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a42734a3929bf84cf0116c9856a3c18c
+
+COUNT = 106
+KEY = ffffffffffffffffffffffffffe0000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e3abc4939457422bb957da3c56938c6d
+
+COUNT = 107
+KEY = fffffffffffffffffffffffffff0000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 972bdd2e7c525130fadc8f76fc6f4b3f
+
+COUNT = 108
+KEY = fffffffffffffffffffffffffff8000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 84a83d7b94c699cbcb8a7d9b61f64093
+
+COUNT = 109
+KEY = fffffffffffffffffffffffffffc000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ce61d63514aded03d43e6ebfc3a9001f
+
+COUNT = 110
+KEY = fffffffffffffffffffffffffffe000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6c839dd58eeae6b8a36af48ed63d2dc9
+
+COUNT = 111
+KEY = ffffffffffffffffffffffffffff000000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cd5ece55b8da3bf622c4100df5de46f9
+
+COUNT = 112
+KEY = ffffffffffffffffffffffffffff800000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3b6f46f40e0ac5fc0a9c1105f800f48d
+
+COUNT = 113
+KEY = ffffffffffffffffffffffffffffc00000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ba26d47da3aeb028de4fb5b3a854a24b
+
+COUNT = 114
+KEY = ffffffffffffffffffffffffffffe00000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 87f53bf620d3677268445212904389d5
+
+COUNT = 115
+KEY = fffffffffffffffffffffffffffff00000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 10617d28b5e0f4605492b182a5d7f9f6
+
+COUNT = 116
+KEY = fffffffffffffffffffffffffffff80000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9aaec4fabbf6fae2a71feff02e372b39
+
+COUNT = 117
+KEY = fffffffffffffffffffffffffffffc0000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3a90c62d88b5c42809abf782488ed130
+
+COUNT = 118
+KEY = fffffffffffffffffffffffffffffe0000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = f1f1c5a40899e15772857ccb65c7a09a
+
+COUNT = 119
+KEY = ffffffffffffffffffffffffffffff0000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 190843d29b25a3897c692ce1dd81ee52
+
+COUNT = 120
+KEY = ffffffffffffffffffffffffffffff8000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a866bc65b6941d86e8420a7ffb0964db
+
+COUNT = 121
+KEY = ffffffffffffffffffffffffffffffc000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8193c6ff85225ced4255e92f6e078a14
+
+COUNT = 122
+KEY = ffffffffffffffffffffffffffffffe000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9661cb2424d7d4a380d547f9e7ec1cb9
+
+COUNT = 123
+KEY = fffffffffffffffffffffffffffffff000000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 86f93d9ec08453a071e2e2877877a9c8
+
+COUNT = 124
+KEY = fffffffffffffffffffffffffffffff800000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 27eefa80ce6a4a9d598e3fec365434d2
+
+COUNT = 125
+KEY = fffffffffffffffffffffffffffffffc00000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d62068444578e3ab39ce7ec95dd045dc
+
+COUNT = 126
+KEY = fffffffffffffffffffffffffffffffe00000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b5f71d4dd9a71fe5d8bc8ba7e6ea3048
+
+COUNT = 127
+KEY = ffffffffffffffffffffffffffffffff00000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6825a347ac479d4f9d95c5cb8d3fd7e9
+
+COUNT = 128
+KEY = ffffffffffffffffffffffffffffffff80000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e3714e94a5778955cc0346358e94783a
+
+COUNT = 129
+KEY = ffffffffffffffffffffffffffffffffc0000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d836b44bb29e0c7d89fa4b2d4b677d2a
+
+COUNT = 130
+KEY = ffffffffffffffffffffffffffffffffe0000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5d454b75021d76d4b84f873a8f877b92
+
+COUNT = 131
+KEY = fffffffffffffffffffffffffffffffff0000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c3498f7eced2095314fc28115885b33f
+
+COUNT = 132
+KEY = fffffffffffffffffffffffffffffffff8000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6e668856539ad8e405bd123fe6c88530
+
+COUNT = 133
+KEY = fffffffffffffffffffffffffffffffffc000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8680db7f3a87b8605543cfdbe6754076
+
+COUNT = 134
+KEY = fffffffffffffffffffffffffffffffffe000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6c5d03b13069c3658b3179be91b0800c
+
+COUNT = 135
+KEY = ffffffffffffffffffffffffffffffffff000000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ef1b384ac4d93eda00c92add0995ea5f
+
+COUNT = 136
+KEY = ffffffffffffffffffffffffffffffffff800000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bf8115805471741bd5ad20a03944790f
+
+COUNT = 137
+KEY = ffffffffffffffffffffffffffffffffffc00000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c64c24b6894b038b3c0d09b1df068b0b
+
+COUNT = 138
+KEY = ffffffffffffffffffffffffffffffffffe00000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3967a10cffe27d0178545fbf6a40544b
+
+COUNT = 139
+KEY = fffffffffffffffffffffffffffffffffff00000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7c85e9c95de1a9ec5a5363a8a053472d
+
+COUNT = 140
+KEY = fffffffffffffffffffffffffffffffffff80000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a9eec03c8abec7ba68315c2c8c2316e0
+
+COUNT = 141
+KEY = fffffffffffffffffffffffffffffffffffc0000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cac8e414c2f388227ae14986fc983524
+
+COUNT = 142
+KEY = fffffffffffffffffffffffffffffffffffe0000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5d942b7f4622ce056c3ce3ce5f1dd9d6
+
+COUNT = 143
+KEY = ffffffffffffffffffffffffffffffffffff0000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d240d648ce21a3020282c3f1b528a0b6
+
+COUNT = 144
+KEY = ffffffffffffffffffffffffffffffffffff8000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 45d089c36d5c5a4efc689e3b0de10dd5
+
+COUNT = 145
+KEY = ffffffffffffffffffffffffffffffffffffc000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b4da5df4becb5462e03a0ed00d295629
+
+COUNT = 146
+KEY = ffffffffffffffffffffffffffffffffffffe000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = dcf4e129136c1a4b7a0f38935cc34b2b
+
+COUNT = 147
+KEY = fffffffffffffffffffffffffffffffffffff000000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d9a4c7618b0ce48a3d5aee1a1c0114c4
+
+COUNT = 148
+KEY = fffffffffffffffffffffffffffffffffffff800000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ca352df025c65c7b0bf306fbee0f36ba
+
+COUNT = 149
+KEY = fffffffffffffffffffffffffffffffffffffc00000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 238aca23fd3409f38af63378ed2f5473
+
+COUNT = 150
+KEY = fffffffffffffffffffffffffffffffffffffe00000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 59836a0e06a79691b36667d5380d8188
+
+COUNT = 151
+KEY = ffffffffffffffffffffffffffffffffffffff00000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 33905080f7acf1cdae0a91fc3e85aee4
+
+COUNT = 152
+KEY = ffffffffffffffffffffffffffffffffffffff80000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 72c9e4646dbc3d6320fc6689d93e8833
+
+COUNT = 153
+KEY = ffffffffffffffffffffffffffffffffffffffc0000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ba77413dea5925b7f5417ea47ff19f59
+
+COUNT = 154
+KEY = ffffffffffffffffffffffffffffffffffffffe0000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6cae8129f843d86dc786a0fb1a184970
+
+COUNT = 155
+KEY = fffffffffffffffffffffffffffffffffffffff0000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fcfefb534100796eebbd990206754e19
+
+COUNT = 156
+KEY = fffffffffffffffffffffffffffffffffffffff8000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8c791d5fdddf470da04f3e6dc4a5b5b5
+
+COUNT = 157
+KEY = fffffffffffffffffffffffffffffffffffffffc000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c93bbdc07a4611ae4bb266ea5034a387
+
+COUNT = 158
+KEY = fffffffffffffffffffffffffffffffffffffffe000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c102e38e489aa74762f3efc5bb23205a
+
+COUNT = 159
+KEY = ffffffffffffffffffffffffffffffffffffffff000000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 93201481665cbafc1fcc220bc545fb3d
+
+COUNT = 160
+KEY = ffffffffffffffffffffffffffffffffffffffff800000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4960757ec6ce68cf195e454cfd0f32ca
+
+COUNT = 161
+KEY = ffffffffffffffffffffffffffffffffffffffffc00000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = feec7ce6a6cbd07c043416737f1bbb33
+
+COUNT = 162
+KEY = ffffffffffffffffffffffffffffffffffffffffe00000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 11c5413904487a805d70a8edd9c35527
+
+COUNT = 163
+KEY = fffffffffffffffffffffffffffffffffffffffff00000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 347846b2b2e36f1f0324c86f7f1b98e2
+
+COUNT = 164
+KEY = fffffffffffffffffffffffffffffffffffffffff80000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 332eee1a0cbd19ca2d69b426894044f0
+
+COUNT = 165
+KEY = fffffffffffffffffffffffffffffffffffffffffc0000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 866b5b3977ba6efa5128efbda9ff03cd
+
+COUNT = 166
+KEY = fffffffffffffffffffffffffffffffffffffffffe0000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cc1445ee94c0f08cdee5c344ecd1e233
+
+COUNT = 167
+KEY = ffffffffffffffffffffffffffffffffffffffffff0000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = be288319029363c2622feba4b05dfdfe
+
+COUNT = 168
+KEY = ffffffffffffffffffffffffffffffffffffffffff8000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cfd1875523f3cd21c395651e6ee15e56
+
+COUNT = 169
+KEY = ffffffffffffffffffffffffffffffffffffffffffc000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cb5a408657837c53bf16f9d8465dce19
+
+COUNT = 170
+KEY = ffffffffffffffffffffffffffffffffffffffffffe000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ca0bf42cb107f55ccff2fc09ee08ca15
+
+COUNT = 171
+KEY = fffffffffffffffffffffffffffffffffffffffffff000000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = fdd9bbb4a7dc2e4a23536a5880a2db67
+
+COUNT = 172
+KEY = fffffffffffffffffffffffffffffffffffffffffff800000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ede447b362c484993dec9442a3b46aef
+
+COUNT = 173
+KEY = fffffffffffffffffffffffffffffffffffffffffffc00000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 10dffb05904bff7c4781df780ad26837
+
+COUNT = 174
+KEY = fffffffffffffffffffffffffffffffffffffffffffe00000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c33bc13e8de88ac25232aa7496398783
+
+COUNT = 175
+KEY = ffffffffffffffffffffffffffffffffffffffffffff00000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ca359c70803a3b2a3d542e8781dea975
+
+COUNT = 176
+KEY = ffffffffffffffffffffffffffffffffffffffffffff80000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = bcc65b526f88d05b89ce8a52021fdb06
+
+COUNT = 177
+KEY = ffffffffffffffffffffffffffffffffffffffffffffc0000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = db91a38855c8c4643851fbfb358b0109
+
+COUNT = 178
+KEY = ffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ca6e8893a114ae8e27d5ab03a5499610
+
+COUNT = 179
+KEY = fffffffffffffffffffffffffffffffffffffffffffff0000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6629d2b8df97da728cdd8b1e7f945077
+
+COUNT = 180
+KEY = fffffffffffffffffffffffffffffffffffffffffffff8000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4570a5a18cfc0dd582f1d88d5c9a1720
+
+COUNT = 181
+KEY = fffffffffffffffffffffffffffffffffffffffffffffc000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 72bc65aa8e89562e3f274d45af1cd10b
+
+COUNT = 182
+KEY = fffffffffffffffffffffffffffffffffffffffffffffe000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 98551da1a6503276ae1c77625f9ea615
+
+COUNT = 183
+KEY = ffffffffffffffffffffffffffffffffffffffffffffff000000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 0ddfe51ced7e3f4ae927daa3fe452cee
+
+COUNT = 184
+KEY = ffffffffffffffffffffffffffffffffffffffffffffff800000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = db826251e4ce384b80218b0e1da1dd4c
+
+COUNT = 185
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffc00000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2cacf728b88abbad7011ed0e64a1680c
+
+COUNT = 186
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffe00000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 330d8ee7c5677e099ac74c9994ee4cfb
+
+COUNT = 187
+KEY = fffffffffffffffffffffffffffffffffffffffffffffff00000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = edf61ae362e882ddc0167474a7a77f3a
+
+COUNT = 188
+KEY = fffffffffffffffffffffffffffffffffffffffffffffff80000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6168b00ba7859e0970ecfd757efecf7c
+
+COUNT = 189
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffc0000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d1415447866230d28bb1ea18a4cdfd02
+
+COUNT = 190
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 516183392f7a8763afec68a060264141
+
+COUNT = 191
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 77565c8d73cfd4130b4aa14d8911710f
+
+COUNT = 192
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffff8000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 37232a4ed21ccc27c19c9610078cabac
+
+COUNT = 193
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffc000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 804f32ea71828c7d329077e712231666
+
+COUNT = 194
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d64424f23cb97215e9c2c6f28d29eab7
+
+COUNT = 195
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 023e82b533f68c75c238cebdb2ee89a2
+
+COUNT = 196
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffff800000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 193a3d24157a51f1ee0893f6777417e7
+
+COUNT = 197
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffc00000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 84ecacfcd400084d078612b1945f2ef5
+
+COUNT = 198
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffe00000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1dcd8bb173259eb33a5242b0de31a455
+
+COUNT = 199
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 35e9eddbc375e792c19992c19165012b
+
+COUNT = 200
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8a772231c01dfdd7c98e4cfddcc0807a
+
+COUNT = 201
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffc0000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6eda7ff6b8319180ff0d6e65629d01c3
+
+COUNT = 202
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = c267ef0e2d01a993944dd397101413cb
+
+COUNT = 203
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e9f80e9d845bcc0f62926af72eabca39
+
+COUNT = 204
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffff8000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 6702990727aa0878637b45dcd3a3b074
+
+COUNT = 205
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffc000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2e2e647d5360e09230a5d738ca33471e
+
+COUNT = 206
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1f56413c7add6f43d1d56e4f02190330
+
+COUNT = 207
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 69cd0606e15af729d6bca143016d9842
+
+COUNT = 208
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffff800000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a085d7c1a500873a20099c4caa3c3f5b
+
+COUNT = 209
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffc00000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4fc0d230f8891415b87b83f95f2e09d1
+
+COUNT = 210
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4327d08c523d8eba697a4336507d1f42
+
+COUNT = 211
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7a15aab82701efa5ae36ab1d6b76290f
+
+COUNT = 212
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5bf0051893a18bb30e139a58fed0fa54
+
+COUNT = 213
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffc0000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 97e8adf65638fd9cdf3bc22c17fe4dbd
+
+COUNT = 214
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1ee6ee326583a0586491c96418d1a35d
+
+COUNT = 215
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 26b549c2ec756f82ecc48008e529956b
+
+COUNT = 216
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffff8000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 70377b6da669b072129e057cc28e9ca5
+
+COUNT = 217
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffc000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9c94b8b0cb8bcc919072262b3fa05ad9
+
+COUNT = 218
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2fbb83dfd0d7abcb05cd28cad2dfb523
+
+COUNT = 219
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 96877803de77744bb970d0a91f4debae
+
+COUNT = 220
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffff800000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7379f3370cf6e5ce12ae5969c8eea312
+
+COUNT = 221
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 02dc99fa3d4f98ce80985e7233889313
+
+COUNT = 222
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1e38e759075ba5cab6457da51844295a
+
+COUNT = 223
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 70bed8dbf615868a1f9d9b05d3e7a267
+
+COUNT = 224
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 234b148b8cb1d8c32b287e896903d150
+
+COUNT = 225
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 294b033df4da853f4be3e243f7e513f4
+
+COUNT = 226
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3f58c950f0367160adec45f2441e7411
+
+COUNT = 227
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 37f655536a704e5ace182d742a820cf4
+
+COUNT = 228
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ea7bd6bb63418731aeac790fe42d61e8
+
+COUNT = 229
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffc000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = e74a4c999b4c064e48bb1e413f51e5ea
+
+COUNT = 230
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = ba9ebefdb4ccf30f296cecb3bc1943e8
+
+COUNT = 231
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3194367a4898c502c13bb7478640a72d
+
+COUNT = 232
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = da797713263d6f33a5478a65ef60d412
+
+COUNT = 233
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d1ac39bb1ef86b9c1344f214679aa376
+
+COUNT = 234
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2fdea9e650532be5bc0e7325337fd363
+
+COUNT = 235
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d3a204dbd9c2af158b6ca67a5156ce4a
+
+COUNT = 236
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 3a0a0e75a8da36735aee6684d965a778
+
+COUNT = 237
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 52fc3e620492ea99641ea168da5b6d52
+
+COUNT = 238
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d2e0c7f15b4772467d2cfc873000b2ca
+
+COUNT = 239
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 563531135e0c4d70a38f8bdb190ba04e
+
+COUNT = 240
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = a8a39a0f5663f4c0fe5f2d3cafff421a
+
+COUNT = 241
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = d94b5e90db354c1e42f61fabe167b2c0
+
+COUNT = 242
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 50e6d3c9b6698a7cd276f96b1473f35a
+
+COUNT = 243
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 9338f08e0ebee96905d8f2e825208f43
+
+COUNT = 244
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 8b378c86672aa54a3a266ba19d2580ca
+
+COUNT = 245
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cca7c3086f5f9511b31233da7cab9160
+
+COUNT = 246
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 5b40ff4ec9be536ba23035fa4f06064c
+
+COUNT = 247
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 60eb5af8416b257149372194e8b88749
+
+COUNT = 248
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 2f005a8aed8a361c92e440c15520cbd1
+
+COUNT = 249
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 7b03627611678a997717578807a800e2
+
+COUNT = 250
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = cf78618f74f6f3696e0a4779b90b5a77
+
+COUNT = 251
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 03720371a04962eaea0a852e69972858
+
+COUNT = 252
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 1f8a8133aa8ccf70e2bd3285831ca6b7
+
+COUNT = 253
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 27936bd27fb1468fc8b48bc483321725
+
+COUNT = 254
+KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = b07d4f3e2cd2ef2eb545980754dfea0f
+
+COUNT = 255
+KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+PLAINTEXT = 00000000000000000000000000000000
+CIPHERTEXT = 4bf85f1b5d54adbc307b0a048389adcb
+
--- /dev/null
+#include <AES.h>
+#include "printf.h"
+
+AES aes ;
+
+byte key [2*N_BLOCK] ;
+byte plain [N_BLOCK] ;
+byte iv [N_BLOCK] ;
+byte cipher [N_BLOCK] ;
+byte check [N_BLOCK] ;
+
+void print_value (const char * str, byte * a, int bits);
+void prekey_test_var_plaintext (int bits);
+void prekey_test_var_key (int bits);
+void set_bits (int bits, byte * a, int count);
+void check_same (byte * a, byte * b, int bits);
+void monte_carlo (int bits);
+
+int main(int argc, char** argv)
+{
+ printf ("AES library test vectors") ;
+
+ monte_carlo (128) ;
+
+ for (int keysize = 128 ; keysize <= 256 ; keysize += 64)
+ {
+ prekey_test_var_plaintext (keysize) ;
+ prekey_test_var_key (keysize) ;
+ }
+}
+
+
+void prekey_test_var_plaintext (int bits)
+{
+ printf ("\nECB Varying Plaintext %i bits\n",bits) ;
+
+ byte succ ;
+ set_bits (bits, key, 0) ; // all zero key
+ succ = aes.set_key (key, bits) ;
+ if (succ != SUCCESS)
+ printf("Failure set_key\n") ;
+
+
+ for (int bitcount = 1 ; bitcount <= 128 ; bitcount++)
+ {
+ printf ("COUNT = %i \n",bitcount-1);
+ print_value ("KEY = ", key, bits) ;
+ set_bits (128, plain, bitcount) ;
+
+ print_value ("PLAINTEXT = ", plain, 128) ;
+
+ succ = aes.encrypt (plain, cipher) ;
+ if (succ != SUCCESS)
+ printf ("Failure encrypt\n") ;
+
+ print_value ("CIPHERTEXT = ", cipher, 128) ;
+
+ succ = aes.decrypt (cipher, check) ;
+ if (succ != SUCCESS)
+ printf ("Failure decrypt\n") ;
+
+ //print_value ("CHECK = ", check, 128) ;
+ check_same (plain, check, 128) ;
+ printf ("\n") ;
+ }
+}
+
+
+void prekey_test_var_key (int bits)
+{
+ printf ("\nECB Varying key %i bits\n",bits);
+
+ byte succ ;
+ set_bits (128, plain, 0) ;
+
+ for (int bitcount = 1 ; bitcount <= bits ; bitcount++)
+ {
+ set_bits (bits, key, bitcount) ; // all zero key
+ succ = aes.set_key (key, bits) ;
+ if (succ != SUCCESS)
+ printf ("Failure set_key\n") ;
+ printf ("COUNT = %i\n",bitcount-1);
+ print_value ("KEY = ", key, bits) ;
+
+ print_value ("PLAINTEXT = ", plain, 128) ;
+
+ succ = aes.encrypt (plain, cipher) ;
+ if (succ != SUCCESS)
+ printf ("Failure encrypt\n") ;
+
+ print_value ("CIPHERTEXT = ", cipher, 128) ;
+
+ succ = aes.decrypt (cipher, check) ;
+ if (succ != SUCCESS)
+ printf ("Failure decrypt\n") ;
+
+ check_same (plain, check, 128) ;
+ printf("\n");
+ }
+}
+
+void set_bits (int bits, byte * a, int count)
+{
+ bits >>= 3 ;
+ byte bcount = count >> 3 ;
+ for (byte i = 0 ; i < bcount ; i++)
+ a [i] = 0xFF ;
+ if ((count & 7) != 0)
+ a [bcount++] = 0xFF & (0xFF00 >> (count & 7)) ;
+ for (byte i = bcount ; i < bits ; i++)
+ a [i] = 0x00 ;
+}
+
+void check_same (byte * a, byte * b, int bits)
+{
+ bits >>= 3 ;
+ for (byte i = 0 ; i < bits ; i++)
+ if (a[i] != b[i])
+ {
+ printf ("Failure plain != check\n") ;
+ return ;
+ }
+}
+
+char hex[] = "0123456789abcdef" ;
+
+
+void print_value (const char * str, byte * a, int bits)
+{
+ printf ("%s",str) ;
+ bits >>= 3 ;
+ for (int i = 0 ; i < bits ; i++)
+ {
+ byte b = a[i] ;
+ printf("%c%c",hex[b >> 4],hex [b & 15]);
+ //Serial.print (hex [b >> 4]) ;
+ //Serial.print (hex [b & 15]) ;
+ }
+ printf("\n") ;
+}
+
+byte monteplain [] =
+ { 0xb9, 0x14, 0x5a, 0x76, 0x8b, 0x7d, 0xc4, 0x89,
+ 0xa0, 0x96, 0xb5, 0x46, 0xf4, 0x3b, 0x23, 0x1f } ;
+byte montekey [] =
+ { 0x13, 0x9a, 0x35, 0x42, 0x2f, 0x1d, 0x61, 0xde,
+ 0x3c, 0x91, 0x78, 0x7f, 0xe0, 0x50, 0x7a, 0xfd } ;
+
+void monte_carlo (int bits)
+{
+ printf ("\nMonte Carlo %i bits\n",bits);
+ byte succ;
+ for (int i = 0 ; i < 16 ; i++)
+ {
+ plain [i] = monteplain [i] ;
+ key [i] = montekey [i] ;
+ }
+ for (int i = 0 ; i < 100 ; i++)
+ {
+ printf ("COUNT = %i\n",i);
+ print_value ("KEY = ", key, bits) ;
+ print_value ("PLAINTEXT = ", plain, 128) ;
+ succ = aes.set_key (key, bits) ;
+ for (int j = 0 ; j < 1000 ; j++)
+ {
+ succ = aes.encrypt (plain, cipher) ;
+ aes.copy_n_bytes (plain, cipher, 16) ;
+ }
+ print_value ("CIPHERTEXT = ", cipher, 128) ;
+ printf("\n");
+ if (bits == 128)
+ {
+ for (byte k = 0 ; k < 16 ; k++)
+ key [k] ^= cipher [k] ;
+ }
+ else if (bits == 192)
+ {
+ }
+ else
+ {
+ }
+ }
+}
--- /dev/null
+AES KEYWORD1
+set_key KEYWORD2
+clean KEYWORD2
+encrypt KEYWORD2
+decrypt KEYWORD2
+cbc_encrypt KEYWORD2
+cbc_decrypt KEYWORD2
--- /dev/null
+/*
+ Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+ */
+ /* Galileo support from spaniakos <spaniakos@gmail.com> */
+
+/**
+ * @file printf.h
+ *
+ * Setup necessary to direct stdout to the Arduino Serial library, which
+ * enables 'printf'
+ */
+
+#ifndef __PRINTF_H__
+#define __PRINTF_H__
+
+#if defined (ARDUINO) && !defined (__arm__) && !defined(__ARDUINO_X86__)
+
+int serial_putc( char c, FILE * )
+{
+ Serial.write( c );
+
+ return c;
+}
+
+void printf_begin(void)
+{
+ fdevopen( &serial_putc, 0 );
+}
+
+#elif defined (__arm__)
+
+void printf_begin(void){}
+
+#elif defined(__ARDUINO_X86__)
+int serial_putc( char c, FILE * )
+{
+ Serial.write( c );
+
+ return c;
+}
+
+void printf_begin(void)
+{
+ //JESUS - For reddirect stdout to /dev/ttyGS0 (Serial Monitor port)
+ stdout = freopen("/dev/ttyGS0","w",stdout);
+ delay(500);
+ printf("redirecting to Serial...");
+
+ //JESUS -----------------------------------------------------------
+}
+#else
+#error This example is only for use on Arduino.
+#endif // ARDUINO
+
+#endif // __PRINTF_H__
--- /dev/null
+aes/
+gf256mul/
+memxor/
+bcal/
+*.swp
+*.o
+.DS_Store
--- /dev/null
+/*
+ This file is part of the aeslib.
+ Copyright (C) 2012 Davy Landman (davy.landman@gmail.com)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+#include "AESLib.h"
+#include <stdint.h>
+#include "aes.h"
+#include "blockcipher_descriptor.h"
+#include "bcal_aes128.h"
+#include "bcal_aes192.h"
+#include "bcal-cbc.h"
+#if (defined(__AVR__))
+#include <avr\pgmspace.h>
+#else
+#include <pgmspace.h>
+#endif
+
+// encrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+void aes128_cbc_enc(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t ctx;
+ uint8_t r;
+ r = bcal_cbc_init(&aes128_desc, key, 128, &ctx);
+ if (r) {
+ return;
+ }
+ bcal_cbc_encMsg(iv, data, data_len / 16, &ctx);
+ bcal_cbc_free(&ctx);
+}
+
+// encrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+void aes192_cbc_enc(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t ctx;
+ uint8_t r;
+ r = bcal_cbc_init(&aes192_desc, key, 192, &ctx);
+ if (r) {
+ return;
+ }
+ bcal_cbc_encMsg(iv, data, data_len / 16, &ctx);
+ bcal_cbc_free(&ctx);
+}
+
+// encrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+void aes128_enc_single(const uint8_t* key, void* data){
+ aes128_ctx_t ctx;
+ aes128_init(key, &ctx);
+ aes128_enc(data, &ctx);
+}
+
+// encrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key is assumed to be 256bit thus 32 uint8_t's
+void aes256_enc_single(const uint8_t* key, void* data){
+ aes256_ctx_t ctx;
+ aes256_init(key, &ctx);
+ aes256_enc(data, &ctx);
+}
+
+
+// prepare an encrypted to use for encrypting multiple blocks lateron.
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+aes_context aes128_cbc_enc_start(const uint8_t* key, const void* iv){
+ bcal_cbc_ctx_t* ctx = (bcal_cbc_ctx_t*)malloc(sizeof(bcal_cbc_ctx_t));
+ uint8_t r = bcal_cbc_init(&aes128_desc, key, 128, ctx);
+ if (r) {
+ free(ctx);
+ return NULL;
+ }
+ bcal_cbc_loadIV(iv, ctx);
+ return (aes_context)ctx;
+}
+
+// prepare an encrypted to use for encrypting multiple blocks lateron.
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+aes_context aes192_cbc_enc_start(const uint8_t* key, const void* iv){
+ bcal_cbc_ctx_t* ctx = (bcal_cbc_ctx_t*)malloc(sizeof(bcal_cbc_ctx_t));
+ uint8_t r = bcal_cbc_init(&aes192_desc, key, 192, ctx);
+ if (r) {
+ free(ctx);
+ return NULL;
+ }
+ bcal_cbc_loadIV(iv, ctx);
+ return (aes_context)ctx;
+}
+
+// encrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes128_cbc_enc_continue(const aes_context ctx, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t* _ctx = (bcal_cbc_ctx_t*)ctx;
+ uint16_t msg_blocks = data_len / 16;
+ while(msg_blocks--){
+ bcal_cbc_encNext(data, _ctx);
+ data = (uint8_t*)data + _ctx->blocksize_B;
+ }
+}
+
+// encrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes192_cbc_enc_continue(const aes_context ctx, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t* _ctx = (bcal_cbc_ctx_t*)ctx;
+ uint16_t msg_blocks = data_len / 16;
+ while(msg_blocks--){
+ bcal_cbc_encNext(data, _ctx);
+ data = (uint8_t*)data + _ctx->blocksize_B;
+ }
+}
+
+// cleanup encryption context
+void aes128_cbc_enc_finish(const aes_context ctx){
+ bcal_cbc_free((bcal_cbc_ctx_t*)ctx);
+ free(ctx);
+}
+
+// cleanup encryption context
+void aes192_cbc_enc_finish(const aes_context ctx){
+ bcal_cbc_free((bcal_cbc_ctx_t*)ctx);
+ free(ctx);
+}
+
+// decrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+void aes128_cbc_dec(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t ctx;
+ uint8_t r;
+ r = bcal_cbc_init(&aes128_desc, key, 128, &ctx);
+ if (r) {
+ return;
+ }
+ bcal_cbc_decMsg(iv, data, data_len / 16, &ctx);
+ bcal_cbc_free(&ctx);
+}
+
+// decrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+void aes192_cbc_dec(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t ctx;
+ uint8_t r;
+ r = bcal_cbc_init(&aes192_desc, key, 192, &ctx);
+ if (r) {
+ return;
+ }
+ bcal_cbc_decMsg(iv, data, data_len / 16, &ctx);
+ bcal_cbc_free(&ctx);
+}
+
+// decrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key is assumed to be 128bit thus 16 uint8_t's
+void aes128_dec_single(const uint8_t* key, void* data){
+ aes128_ctx_t ctx;
+ aes128_init(key, &ctx);
+ aes128_dec(data, &ctx);
+}
+
+// decrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key is assumed to be 256bit thus 32 uint8_t's
+void aes256_dec_single(const uint8_t* key, void* data){
+ aes256_ctx_t ctx;
+ aes256_init(key, &ctx);
+ aes256_dec(data, &ctx);
+}
+
+
+// prepare an decrypted to use for decrypting multiple blocks lateron.
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+aes_context aes128_cbc_dec_start(const uint8_t* key, const void* iv){
+ bcal_cbc_ctx_t* ctx = (bcal_cbc_ctx_t*)malloc(sizeof(bcal_cbc_ctx_t));
+ uint8_t r = bcal_cbc_init(&aes128_desc, key, 128, ctx);
+ if (r) {
+ free(ctx);
+ return NULL;
+ }
+ bcal_cbc_loadIV(iv, ctx);
+ return (aes_context)ctx;
+}
+
+// prepare an decrypted to use for decrypting multiple blocks lateron.
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+aes_context aes192_cbc_dec_start(const uint8_t* key, const void* iv){
+ bcal_cbc_ctx_t* ctx = (bcal_cbc_ctx_t*)malloc(sizeof(bcal_cbc_ctx_t));
+ uint8_t r = bcal_cbc_init(&aes192_desc, key, 192, ctx);
+ if (r) {
+ free(ctx);
+ return NULL;
+ }
+ bcal_cbc_loadIV(iv, ctx);
+ return (aes_context)ctx;
+}
+
+// decrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes128_cbc_dec_continue(const aes_context ctx, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t* _ctx = (bcal_cbc_ctx_t*)ctx;
+ uint16_t msg_blocks = data_len / 16;
+ while(msg_blocks--){
+ bcal_cbc_decNext(data, _ctx);
+ data = (uint8_t*)data + _ctx->blocksize_B;
+ }
+}
+
+// decrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes192_cbc_dec_continue(const aes_context ctx, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t* _ctx = (bcal_cbc_ctx_t*)ctx;
+ uint16_t msg_blocks = data_len / 16;
+ while(msg_blocks--){
+ bcal_cbc_decNext(data, _ctx);
+ data = (uint8_t*)data + _ctx->blocksize_B;
+ }
+}
+
+// cleanup decryption context
+void aes128_cbc_dec_finish(const aes_context ctx){
+ bcal_cbc_free((bcal_cbc_ctx_t*)ctx);
+ free(ctx);
+}
+
+// cleanup decryption context
+void aes192_cbc_dec_finish(const aes_context ctx){
+ bcal_cbc_free((bcal_cbc_ctx_t*)ctx);
+ free(ctx);
+}
--- /dev/null
+/*
+ This file is part of the aeslib.
+ Copyright (C) 2012 Davy Landman (davy.landman@gmail.com)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+#include "AESLib.h"
+#include <stdint.h>
+#include "aes.h"
+#include "blockcipher_descriptor.h"
+#include "bcal_aes128.h"
+#include "bcal_aes192.h"
+#include "bcal-cbc.h"
+#include <avr/pgmspace.h>
+
+// encrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+void aes128_cbc_enc(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t ctx;
+ uint8_t r;
+ r = bcal_cbc_init(&aes128_desc, key, 128, &ctx);
+ if (r) {
+ return;
+ }
+ bcal_cbc_encMsg(iv, data, data_len / 16, &ctx);
+ bcal_cbc_free(&ctx);
+}
+
+// encrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+void aes192_cbc_enc(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t ctx;
+ uint8_t r;
+ r = bcal_cbc_init(&aes192_desc, key, 192, &ctx);
+ if (r) {
+ return;
+ }
+ bcal_cbc_encMsg(iv, data, data_len / 16, &ctx);
+ bcal_cbc_free(&ctx);
+}
+
+// encrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+void aes128_enc_single(const uint8_t* key, void* data){
+ aes128_ctx_t ctx;
+ aes128_init(key, &ctx);
+ aes128_enc(data, &ctx);
+}
+
+// encrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key is assumed to be 256bit thus 32 uint8_t's
+void aes256_enc_single(const uint8_t* key, void* data){
+ aes256_ctx_t ctx;
+ aes256_init(key, &ctx);
+ aes256_enc(data, &ctx);
+}
+
+
+// prepare an encrypted to use for encrypting multiple blocks lateron.
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+aes_context aes128_cbc_enc_start(const uint8_t* key, const void* iv){
+ bcal_cbc_ctx_t* ctx = (bcal_cbc_ctx_t*)malloc(sizeof(bcal_cbc_ctx_t));
+ uint8_t r = bcal_cbc_init(&aes128_desc, key, 128, ctx);
+ if (r) {
+ free(ctx);
+ return NULL;
+ }
+ bcal_cbc_loadIV(iv, ctx);
+ return (aes_context)ctx;
+}
+
+// prepare an encrypted to use for encrypting multiple blocks lateron.
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+aes_context aes192_cbc_enc_start(const uint8_t* key, const void* iv){
+ bcal_cbc_ctx_t* ctx = (bcal_cbc_ctx_t*)malloc(sizeof(bcal_cbc_ctx_t));
+ uint8_t r = bcal_cbc_init(&aes192_desc, key, 192, ctx);
+ if (r) {
+ free(ctx);
+ return NULL;
+ }
+ bcal_cbc_loadIV(iv, ctx);
+ return (aes_context)ctx;
+}
+
+// encrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes128_cbc_enc_continue(const aes_context ctx, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t* _ctx = (bcal_cbc_ctx_t*)ctx;
+ uint16_t msg_blocks = data_len / 16;
+ while(msg_blocks--){
+ bcal_cbc_encNext(data, _ctx);
+ data = (uint8_t*)data + _ctx->blocksize_B;
+ }
+}
+
+// encrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes192_cbc_enc_continue(const aes_context ctx, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t* _ctx = (bcal_cbc_ctx_t*)ctx;
+ uint16_t msg_blocks = data_len / 16;
+ while(msg_blocks--){
+ bcal_cbc_encNext(data, _ctx);
+ data = (uint8_t*)data + _ctx->blocksize_B;
+ }
+}
+
+// cleanup encryption context
+void aes128_cbc_enc_finish(const aes_context ctx){
+ bcal_cbc_free((bcal_cbc_ctx_t*)ctx);
+ free(ctx);
+}
+
+// cleanup encryption context
+void aes192_cbc_enc_finish(const aes_context ctx){
+ bcal_cbc_free((bcal_cbc_ctx_t*)ctx);
+ free(ctx);
+}
+
+// decrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+void aes128_cbc_dec(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t ctx;
+ uint8_t r;
+ r = bcal_cbc_init(&aes128_desc, key, 128, &ctx);
+ if (r) {
+ return;
+ }
+ bcal_cbc_decMsg(iv, data, data_len / 16, &ctx);
+ bcal_cbc_free(&ctx);
+}
+
+// decrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+void aes192_cbc_dec(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t ctx;
+ uint8_t r;
+ r = bcal_cbc_init(&aes192_desc, key, 192, &ctx);
+ if (r) {
+ return;
+ }
+ bcal_cbc_decMsg(iv, data, data_len / 16, &ctx);
+ bcal_cbc_free(&ctx);
+}
+
+// decrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key is assumed to be 128bit thus 16 uint8_t's
+void aes128_dec_single(const uint8_t* key, void* data){
+ aes128_ctx_t ctx;
+ aes128_init(key, &ctx);
+ aes128_dec(data, &ctx);
+}
+
+// decrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key is assumed to be 256bit thus 32 uint8_t's
+void aes256_dec_single(const uint8_t* key, void* data){
+ aes256_ctx_t ctx;
+ aes256_init(key, &ctx);
+ aes256_dec(data, &ctx);
+}
+
+
+// prepare an decrypted to use for decrypting multiple blocks lateron.
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+aes_context aes128_cbc_dec_start(const uint8_t* key, const void* iv){
+ bcal_cbc_ctx_t* ctx = (bcal_cbc_ctx_t*)malloc(sizeof(bcal_cbc_ctx_t));
+ uint8_t r = bcal_cbc_init(&aes128_desc, key, 128, ctx);
+ if (r) {
+ free(ctx);
+ return NULL;
+ }
+ bcal_cbc_loadIV(iv, ctx);
+ return (aes_context)ctx;
+}
+
+// prepare an decrypted to use for decrypting multiple blocks lateron.
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+aes_context aes192_cbc_dec_start(const uint8_t* key, const void* iv){
+ bcal_cbc_ctx_t* ctx = (bcal_cbc_ctx_t*)malloc(sizeof(bcal_cbc_ctx_t));
+ uint8_t r = bcal_cbc_init(&aes192_desc, key, 192, ctx);
+ if (r) {
+ free(ctx);
+ return NULL;
+ }
+ bcal_cbc_loadIV(iv, ctx);
+ return (aes_context)ctx;
+}
+
+// decrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes128_cbc_dec_continue(const aes_context ctx, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t* _ctx = (bcal_cbc_ctx_t*)ctx;
+ uint16_t msg_blocks = data_len / 16;
+ while(msg_blocks--){
+ bcal_cbc_decNext(data, _ctx);
+ data = (uint8_t*)data + _ctx->blocksize_B;
+ }
+}
+
+// decrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes192_cbc_dec_continue(const aes_context ctx, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t* _ctx = (bcal_cbc_ctx_t*)ctx;
+ uint16_t msg_blocks = data_len / 16;
+ while(msg_blocks--){
+ bcal_cbc_decNext(data, _ctx);
+ data = (uint8_t*)data + _ctx->blocksize_B;
+ }
+}
+
+// cleanup decryption context
+void aes128_cbc_dec_finish(const aes_context ctx){
+ bcal_cbc_free((bcal_cbc_ctx_t*)ctx);
+ free(ctx);
+}
+
+// cleanup decryption context
+void aes192_cbc_dec_finish(const aes_context ctx){
+ bcal_cbc_free((bcal_cbc_ctx_t*)ctx);
+ free(ctx);
+}
--- /dev/null
+/*
+ This file is part of the aeslib.
+ Copyright (C) 2012 Davy Landman (davy.landman@gmail.com)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef AESLIB_H
+#define AESLIB_H
+#include <stdint.h>
+#ifdef __cplusplus
+extern "C"{
+#endif
+// encrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+void aes128_cbc_enc(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len);
+
+// encrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+void aes192_cbc_enc(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len);
+
+// encrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key is assumed to be 128bit thus 16 uint8_t's
+void aes128_enc_single(const uint8_t* key, void* data);
+
+// encrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key is assumed to be 256bit thus 32 uint8_t's
+void aes256_enc_single(const uint8_t* key, void* data);
+
+typedef void* aes_context;
+
+// prepare an encrypted to use for encrypting multiple blocks lateron.
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+aes_context aes128_cbc_enc_start(const uint8_t* key, const void* iv);
+
+// prepare an encrypted to use for encrypting multiple blocks lateron.
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+aes_context aes192_cbc_enc_start(const uint8_t* key, const void* iv);
+
+// encrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes128_cbc_enc_continue(const aes_context ctx, void* data, const uint16_t data_len);
+
+// encrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes192_cbc_enc_continue(const aes_context ctx, void* data, const uint16_t data_len);
+
+// cleanup encryption context
+void aes128_cbc_enc_finish(const aes_context ctx);
+
+// cleanup encryption context
+void aes192_cbc_enc_finish(const aes_context ctx);
+
+// decrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+void aes128_cbc_dec(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len);
+
+// decrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+void aes192_cbc_dec(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len);
+
+// decrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key is assumed to be 128bit thus 16 uint8_t's
+void aes128_dec_single(const uint8_t* key, void* data);
+
+// decrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key is assumed to be 256bit thus 32 uint8_t's
+void aes256_dec_single(const uint8_t* key, void* data);
+
+// prepare an decrypter to use for decrypting multiple blocks lateron.
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+aes_context aes128_cbc_dec_start(const uint8_t* key, const void* iv);
+
+// prepare an decrypter to use for decrypting multiple blocks lateron.
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+aes_context aes192_cbc_dec_start(const uint8_t* key, const void* iv);
+
+// decrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes128_cbc_dec_continue(const aes_context ctx, void* data, const uint16_t data_len);
+
+// decrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes192_cbc_dec_continue(const aes_context ctx, void* data, const uint16_t data_len);
+
+// cleanup decryption context
+void aes128_cbc_dec_finish(const aes_context ctx);
+
+// cleanup decryption context
+void aes192_cbc_dec_finish(const aes_context ctx);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
--- /dev/null
+Arduino AESLib
+==============
+
+This project is just an Arduino ready extract from the [AVR-Crypto-Lib](https://github.com/cantora/avr-crypto-lib).
+
+It only packages the ASM implementations of AES into a library ready to use in
+Arduino IDE.
+
+See the LICENSE file for details of the GPLv3 license in which the AVR-Crypo-Lib
+is licensed.
+
+
+Installation
+------------
+
+- Download the files in this repository (using either clone or the download button)
+- Copy the `AESLib` folder into `libraries` folder (same level as your `sketch` folder)
+- add `#include <AESLib.h>` in your sketch.
+
+
+Usage
+-----
+
+At the moment only 128bit keys are supported, the blocksize is also fixed at 128bit.
+This means that the key array and possible iv array should contain exactly 16 bytes (`uint8_t` or `byte`).
+Moreover the amount of bytes to encrypt should be mod 16.
+(this means you have to take care of padding yourself).
+
+The library supports 3 kinds of operations.
+
+1. single block encryption/decryption
+- multiple block encryption/decryption using CBC (single call)
+- multiple block encryption/decryption using CBC (multiple calls)
+
+The single block enc/decryption are the following methods:
+
+```c
+void aes128_enc_single(const uint8_t* key, void* data);
+void aes128_dec_single(const uint8_t* key, void* data);
+```
+
+Usage example:
+
+```c
+Serial.begin(57600);
+uint8_t key[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+char data[] = "0123456789012345"; //16 chars == 16 bytes
+aes128_enc_single(key, data);
+Serial.print("encrypted:");
+Serial.println(data);
+aes128_dec_single(key, data);
+Serial.print("decrypted:");
+Serial.println(data);
+```
+
+Usage example for AES256:
+
+```c
+Serial.begin(57600);
+uint8_t key[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31};
+char data[] = "0123456789012345";
+aes256_enc_single(key, data);
+Serial.print("encrypted:");
+Serial.println(data);
+aes256_dec_single(key, data);
+Serial.print("decrypted:");
+Serial.println(data);
+```
+
+
+
--- /dev/null
+/* aes.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-30
+ * \license GPLv3 or later
+ *
+ */
+#ifndef AES_H_
+#define AES_H_
+
+#include <stdint.h>
+
+#include "aes_types.h"
+#include "aes128_enc.h"
+#include "aes192_enc.h"
+#include "aes256_enc.h"
+#include "aes128_dec.h"
+#include "aes192_dec.h"
+#include "aes256_dec.h"
+#include "aes_enc.h"
+#include "aes_dec.h"
+#include "aes_keyschedule.h"
+
+#endif
--- /dev/null
+/* aes128_dec.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes128_dec.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-30
+ * \license GPLv3 or later
+ * \ingroup AES
+ */
+
+#ifndef AES128_DEC_H_
+#define AES128_DEC_H_
+
+#include "aes_types.h"
+#include "aes_dec.h"
+
+/**
+ * \brief decrypt with 128 bit key.
+ *
+ * This function decrypts one block with the AES algorithm under control of
+ * a keyschedule produced from a 128 bit key.
+ * \param buffer pointer to the block to decrypt
+ * \param ctx pointer to the key schedule
+ */
+void aes128_dec(void* buffer, aes128_ctx_t* ctx);
+
+
+
+#endif /* AES128_DEC_H_ */
--- /dev/null
+/* aes128_enc.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes128_enc.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-30
+ * \license GPLv3 or later
+ * \ingroup AES
+ */
+
+#ifndef AES128_ENC_H_
+#define AES128_ENC_H_
+
+#include "aes_types.h"
+#include "aes_enc.h"
+
+
+/**
+ * \brief encrypt with 128 bit key.
+ *
+ * This function encrypts one block with the AES algorithm under control of
+ * a keyschedule produced from a 128 bit key.
+ * \param buffer pointer to the block to encrypt
+ * \param ctx pointer to the key schedule
+ */
+void aes128_enc(void* buffer, aes128_ctx_t* ctx);
+
+
+
+#endif /* AES128_ENC_H_ */
--- /dev/null
+/* aes192_dec.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes192_dec.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-31
+ * \license GPLv3 or later
+ * \ingroup AES
+ */
+
+#ifndef AES192_DEC_H_
+#define AES192_DEC_H_
+
+#include "aes_types.h"
+#include "aes_dec.h"
+
+/**
+ * \brief decrypt with 192 bit key.
+ *
+ * This function decrypts one block with the AES algorithm under control of
+ * a keyschedule produced from a 192 bit key.
+ * \param buffer pointer to the block to decrypt
+ * \param ctx pointer to the key schedule
+ */
+void aes192_dec(void* buffer, aes192_ctx_t* ctx);
+
+
+
+#endif /* AES192_DEC_H_ */
--- /dev/null
+/* aes192_enc.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes192_enc.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-31
+ * \license GPLv3 or later
+ * \ingroup AES
+ */
+
+#ifndef AES192_ENC_H_
+#define AES192_ENC_H_
+
+#include "aes_types.h"
+#include "aes_enc.h"
+
+
+/**
+ * \brief encrypt with 192 bit key.
+ *
+ * This function encrypts one block with the AES algorithm under control of
+ * a keyschedule produced from a 192 bit key.
+ * \param buffer pointer to the block to encrypt
+ * \param ctx pointer to the key schedule
+ */
+void aes192_enc(void* buffer, aes192_ctx_t* ctx);
+
+
+
+#endif /* AES192_ENC_H_ */
--- /dev/null
+/* aes256_dec.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes256_dec.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-31
+ * \license GPLv3 or later
+ * \ingroup AES
+ */
+
+#ifndef AES256_DEC_H_
+#define AES256_DEC_H_
+
+#include "aes_types.h"
+#include "aes_dec.h"
+
+/**
+ * \brief decrypt with 256 bit key.
+ *
+ * This function decrypts one block with the AES algorithm under control of
+ * a keyschedule produced from a 256 bit key.
+ * \param buffer pointer to the block to decrypt
+ * \param ctx pointer to the key schedule
+ */
+void aes256_dec(void* buffer, aes256_ctx_t* ctx);
+
+
+
+#endif /* AES256_DEC_H_ */
--- /dev/null
+/* aes256_enc.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes256_enc.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-31
+ * \license GPLv3 or later
+ * \ingroup AES
+ */
+
+#ifndef AES256_ENC_H_
+#define AES256_ENC_H_
+
+#include "aes_types.h"
+#include "aes_enc.h"
+
+
+/**
+ * \brief encrypt with 256 bit key.
+ *
+ * This function encrypts one block with the AES algorithm under control of
+ * a keyschedule produced from a 256 bit key.
+ * \param buffer pointer to the block to encrypt
+ * \param ctx pointer to the key schedule
+ */
+void aes256_enc(void* buffer, aes256_ctx_t* ctx);
+
+
+
+#endif /* AES256_ENC_H_ */
--- /dev/null
+/* aes_dec-asm.S */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008, 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes_dec-asm.S
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-10
+ * \license GPLv3 or later
+ *
+ */
+
+#include "avr-asm-macros.S"
+A = 28
+B = 29
+P = 0
+xREDUCER = 25
+
+.global aes256_dec
+aes256_dec:
+ ldi r20, 14
+ rjmp aes_decrypt_core
+
+.global aes192_dec
+aes192_dec:
+ ldi r20, 12
+ rjmp aes_decrypt_core
+
+.global aes128_dec
+aes128_dec:
+ ldi r20, 10
+
+
+/*
+ void aes_decrypt_core(aes_cipher_state_t* state, const aes_genctx_t* ks, uint8_t rounds)
+*/
+T0= 2
+T1= 3
+T2= 4
+T3= 5
+T4 = 6
+T5 = 7
+ST00 = 8
+ST01 = 9
+ST02 = 10
+ST03 = 11
+ST10 = 12
+ST11 = 13
+ST12 = 14
+ST13 = 15
+ST20 = 16
+ST21 = 17
+ST22 = 18
+ST23 = 19
+ST30 = 20
+ST31 = 21
+ST32 = 22
+ST33 = 23
+CTR = 24
+/*
+ * param state: r24:r25
+ * param ks: r22:r23
+ * param rounds: r20
+ */
+.global aes_decrypt_core
+aes_decrypt_core:
+ push_range 2, 17
+ push r28
+ push r29
+ push r24
+ push r25
+ movw r26, r22
+ movw r30, r24
+ mov CTR, r20
+ inc r20
+ swap r20 /* r20*16 */
+ add r26, r20
+ adc r27, r1
+ clt
+ .irp param, ST00, ST01, ST02, ST03, ST10, ST11, ST12, ST13, ST20, ST21, ST22, ST23, ST30, ST31, ST32, ST33
+ ld \param, Z+
+ .endr
+
+ ldi xREDUCER, 0x1b /* load reducer */
+
+
+ .irp param, ST33, ST32, ST31, ST30, ST23, ST22, ST21, ST20, ST13, ST12, ST11, ST10, ST03, ST02, ST01, ST00
+ ld r0, -X
+ eor \param, r0
+ .endr
+1:
+ dec CTR
+ brne 2f
+ set
+2:
+ ldi r31, hi8(aes_invsbox)
+ /* substitute and invShift */
+ .irp param, ST00, ST10, ST20, ST30
+ mov r30, \param
+ lpm \param, Z
+ .endr
+ mov r30, ST31
+ lpm T0, Z
+ mov r30, ST21
+ lpm ST31, Z
+ mov r30, ST11
+ lpm ST21, Z
+ mov r30, ST01
+ lpm ST11, Z
+ mov ST01, T0
+
+ mov r30, ST32
+ lpm T0, Z
+ mov r30, ST22
+ lpm T1,Z
+ mov r30, ST12
+ lpm ST32, Z
+ mov r30, ST02
+ lpm ST22, Z
+ mov ST12, T0
+ mov ST02, T1
+
+ mov r30, ST03
+ lpm T0, Z
+ mov r30, ST13
+ lpm ST03, Z
+ mov r30, ST23
+ lpm ST13, Z
+ mov r30, ST33
+ lpm ST23, Z
+ mov ST33, T0
+
+ /* key addition */
+ .irp param, ST33, ST32, ST31, ST30, ST23, ST22, ST21, ST20, ST13, ST12, ST11, ST10, ST03, ST02, ST01, ST00
+ ld r0, -X
+ eor \param, r0
+ .endr
+ brtc 2f
+exit:
+ pop r31
+ pop r30
+ st Z+, ST00
+ st Z+, ST01
+ st Z+, ST02
+ st Z+, ST03
+ st Z+, ST10
+ st Z+, ST11
+ st Z+, ST12
+ st Z+, ST13
+ st Z+, ST20
+ st Z+, ST21
+ st Z+, ST22
+ st Z+, ST23
+ st Z+, ST30
+ st Z+, ST31
+ st Z+, ST32
+ st Z+, ST33
+ pop r29
+ pop r28
+ pop_range 2, 17
+ ret
+2:
+ /* inv column (row) mixing*/
+ /* invMixCol (Row) 1 */
+ /* preparing */
+ ldi r31, hi8(lut_gf256mul_0x09)
+ mov T0, ST03
+ eor T0, ST02 ; T0 = t
+ mov T1, ST00
+ eor T1, ST01 ; T1 = u
+ mov r30, T0
+ eor r30, T1
+ lpm T2, Z ; T2 = v'
+
+ ldi r31, hi8(lut_gf256mul_0x04)
+ mov r30, ST02
+ eor r30, ST00
+ lpm T3, Z
+ eor T3, T2; T3 = w
+
+ mov r30, ST03
+ eor r30, ST01
+ lpm P, Z ; T2 = v
+ eor T2, P
+
+ /* now the big move */
+ mov T4, ST00
+ eor T4, ST03
+ lsl T4
+ brcc 3f
+ eor T4, xREDUCER
+3: eor T4, T2
+ eor ST03, T4
+
+ mov T4, ST02
+ eor T4, ST01
+ lsl T4
+ brcc 3f
+ eor T4, xREDUCER
+3: eor T4, T2
+ eor ST01, T4
+
+ lsl T0
+ brcc 3f
+ eor T0, xREDUCER
+3: eor T0, T3
+ eor ST02, T0
+
+ lsl T1
+ brcc 3f
+ eor T1, xREDUCER
+3: eor T1, T3
+ eor ST00, T1
+
+ /* invMixCol (Row) 2 */
+ /* preparing */
+ ldi r31, hi8(lut_gf256mul_0x09)
+ mov T0, ST13
+ eor T0, ST12 ; T0 = t
+ mov T1, ST10
+ eor T1, ST11 ; T1 = u
+ mov r30, T0
+ eor r30, T1
+
+ lpm T2, Z ; T2 = v'
+
+ ldi r31, hi8(lut_gf256mul_0x04)
+ mov r30, ST12
+ eor r30, ST10
+ lpm T3, Z
+ eor T3, T2; T3 = w
+
+ mov r30, ST13
+ eor r30, ST11
+ lpm P, Z
+ eor T2, P ; T2 = v
+
+ /* now the big move */
+ mov T4, ST10
+ eor T4, ST13
+ lsl T4
+ brcc 3f
+ eor T4, xREDUCER
+3: eor T4, T2
+ eor ST13, T4
+
+ mov T4, ST12
+ eor T4, ST11
+ lsl T4
+ brcc 3f
+ eor T4, xREDUCER
+3: eor T4, T2
+ eor ST11, T4
+
+ lsl T0
+ brcc 3f
+ eor T0, xREDUCER
+3: eor T0, T3
+ eor ST12, T0
+
+ lsl T1
+ brcc 3f
+ eor T1, xREDUCER
+3: eor T1, T3
+ eor ST10, T1
+
+ /* invMixCol (Row) 2 */
+ /* preparing */
+ ldi r31, hi8(lut_gf256mul_0x09)
+ mov T0, ST23
+ eor T0, ST22 ; T0 = t
+ mov T1, ST20
+ eor T1, ST21 ; T1 = u
+ mov r30, T0
+ eor r30, T1
+
+ lpm T2, Z ; T2 = v'
+
+ ldi r31, hi8(lut_gf256mul_0x04)
+ mov r30, ST22
+ eor r30, ST20
+ lpm T3, Z
+ eor T3, T2; T3 = w
+
+ mov r30, ST23
+ eor r30, ST21
+ lpm P, Z
+ eor T2, P ; T2 = v
+
+ /* now the big move */
+ mov T4, ST20
+ eor T4, ST23
+ lsl T4
+ brcc 3f
+ eor T4, xREDUCER
+3: eor T4, T2
+ eor ST23, T4
+
+ mov T4, ST22
+ eor T4, ST21
+ lsl T4
+ brcc 3f
+ eor T4, xREDUCER
+3: eor T4, T2
+ eor ST21, T4
+
+ lsl T0
+ brcc 3f
+ eor T0, xREDUCER
+3: eor T0, T3
+ eor ST22, T0
+
+ lsl T1
+ brcc 3f
+ eor T1, xREDUCER
+3: eor T1, T3
+ eor ST20, T1
+
+ /* invMixCol (Row) 3 */
+ /* preparing */
+ ldi r31, hi8(lut_gf256mul_0x09)
+ mov T0, ST33
+ eor T0, ST32 ; T0 = t
+ mov T1, ST30
+ eor T1, ST31 ; T1 = u
+ mov r30, T0
+ eor r30, T1
+
+ lpm T2, Z ; T2 = v'
+
+ ldi r31, hi8(lut_gf256mul_0x04)
+ mov r30, ST32
+ eor r30, ST30
+ lpm T3, Z
+ eor T3, T2; T3 = w
+
+ mov r30, ST33
+ eor r30, ST31
+ lpm P, Z
+ eor T2, P ; T2 = v
+
+ /* now the big move */
+ mov T4, ST30
+ eor T4, ST33
+ lsl T4
+ brcc 3f
+ eor T4, xREDUCER
+3: eor T4, T2
+ eor ST33, T4
+
+ mov T4, ST32
+ eor T4, ST31
+ lsl T4
+ brcc 3f
+ eor T4, xREDUCER
+3: eor T4, T2
+ eor ST31, T4
+
+ lsl T0
+ brcc 3f
+ eor T0, xREDUCER
+3: eor T0, T3
+ eor ST32, T0
+
+ lsl T1
+ brcc 3f
+ eor T1, xREDUCER
+3: eor T1, T3
+ eor ST30, T1
+
+ rjmp 1b
+
+.balign 256
+
+lut_gf256mul_0x09:
+.byte 0x00, 0x09, 0x12, 0x1B, 0x24, 0x2D, 0x36, 0x3F
+.byte 0x48, 0x41, 0x5A, 0x53, 0x6C, 0x65, 0x7E, 0x77
+.byte 0x90, 0x99, 0x82, 0x8B, 0xB4, 0xBD, 0xA6, 0xAF
+.byte 0xD8, 0xD1, 0xCA, 0xC3, 0xFC, 0xF5, 0xEE, 0xE7
+.byte 0x3B, 0x32, 0x29, 0x20, 0x1F, 0x16, 0x0D, 0x04
+.byte 0x73, 0x7A, 0x61, 0x68, 0x57, 0x5E, 0x45, 0x4C
+.byte 0xAB, 0xA2, 0xB9, 0xB0, 0x8F, 0x86, 0x9D, 0x94
+.byte 0xE3, 0xEA, 0xF1, 0xF8, 0xC7, 0xCE, 0xD5, 0xDC
+.byte 0x76, 0x7F, 0x64, 0x6D, 0x52, 0x5B, 0x40, 0x49
+.byte 0x3E, 0x37, 0x2C, 0x25, 0x1A, 0x13, 0x08, 0x01
+.byte 0xE6, 0xEF, 0xF4, 0xFD, 0xC2, 0xCB, 0xD0, 0xD9
+.byte 0xAE, 0xA7, 0xBC, 0xB5, 0x8A, 0x83, 0x98, 0x91
+.byte 0x4D, 0x44, 0x5F, 0x56, 0x69, 0x60, 0x7B, 0x72
+.byte 0x05, 0x0C, 0x17, 0x1E, 0x21, 0x28, 0x33, 0x3A
+.byte 0xDD, 0xD4, 0xCF, 0xC6, 0xF9, 0xF0, 0xEB, 0xE2
+.byte 0x95, 0x9C, 0x87, 0x8E, 0xB1, 0xB8, 0xA3, 0xAA
+.byte 0xEC, 0xE5, 0xFE, 0xF7, 0xC8, 0xC1, 0xDA, 0xD3
+.byte 0xA4, 0xAD, 0xB6, 0xBF, 0x80, 0x89, 0x92, 0x9B
+.byte 0x7C, 0x75, 0x6E, 0x67, 0x58, 0x51, 0x4A, 0x43
+.byte 0x34, 0x3D, 0x26, 0x2F, 0x10, 0x19, 0x02, 0x0B
+.byte 0xD7, 0xDE, 0xC5, 0xCC, 0xF3, 0xFA, 0xE1, 0xE8
+.byte 0x9F, 0x96, 0x8D, 0x84, 0xBB, 0xB2, 0xA9, 0xA0
+.byte 0x47, 0x4E, 0x55, 0x5C, 0x63, 0x6A, 0x71, 0x78
+.byte 0x0F, 0x06, 0x1D, 0x14, 0x2B, 0x22, 0x39, 0x30
+.byte 0x9A, 0x93, 0x88, 0x81, 0xBE, 0xB7, 0xAC, 0xA5
+.byte 0xD2, 0xDB, 0xC0, 0xC9, 0xF6, 0xFF, 0xE4, 0xED
+.byte 0x0A, 0x03, 0x18, 0x11, 0x2E, 0x27, 0x3C, 0x35
+.byte 0x42, 0x4B, 0x50, 0x59, 0x66, 0x6F, 0x74, 0x7D
+.byte 0xA1, 0xA8, 0xB3, 0xBA, 0x85, 0x8C, 0x97, 0x9E
+.byte 0xE9, 0xE0, 0xFB, 0xF2, 0xCD, 0xC4, 0xDF, 0xD6
+.byte 0x31, 0x38, 0x23, 0x2A, 0x15, 0x1C, 0x07, 0x0E
+.byte 0x79, 0x70, 0x6B, 0x62, 0x5D, 0x54, 0x4F, 0x46
+
+lut_gf256mul_0x04:
+.byte 0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C
+.byte 0x20, 0x24, 0x28, 0x2C, 0x30, 0x34, 0x38, 0x3C
+.byte 0x40, 0x44, 0x48, 0x4C, 0x50, 0x54, 0x58, 0x5C
+.byte 0x60, 0x64, 0x68, 0x6C, 0x70, 0x74, 0x78, 0x7C
+.byte 0x80, 0x84, 0x88, 0x8C, 0x90, 0x94, 0x98, 0x9C
+.byte 0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC
+.byte 0xC0, 0xC4, 0xC8, 0xCC, 0xD0, 0xD4, 0xD8, 0xDC
+.byte 0xE0, 0xE4, 0xE8, 0xEC, 0xF0, 0xF4, 0xF8, 0xFC
+.byte 0x1B, 0x1F, 0x13, 0x17, 0x0B, 0x0F, 0x03, 0x07
+.byte 0x3B, 0x3F, 0x33, 0x37, 0x2B, 0x2F, 0x23, 0x27
+.byte 0x5B, 0x5F, 0x53, 0x57, 0x4B, 0x4F, 0x43, 0x47
+.byte 0x7B, 0x7F, 0x73, 0x77, 0x6B, 0x6F, 0x63, 0x67
+.byte 0x9B, 0x9F, 0x93, 0x97, 0x8B, 0x8F, 0x83, 0x87
+.byte 0xBB, 0xBF, 0xB3, 0xB7, 0xAB, 0xAF, 0xA3, 0xA7
+.byte 0xDB, 0xDF, 0xD3, 0xD7, 0xCB, 0xCF, 0xC3, 0xC7
+.byte 0xFB, 0xFF, 0xF3, 0xF7, 0xEB, 0xEF, 0xE3, 0xE7
+.byte 0x36, 0x32, 0x3E, 0x3A, 0x26, 0x22, 0x2E, 0x2A
+.byte 0x16, 0x12, 0x1E, 0x1A, 0x06, 0x02, 0x0E, 0x0A
+.byte 0x76, 0x72, 0x7E, 0x7A, 0x66, 0x62, 0x6E, 0x6A
+.byte 0x56, 0x52, 0x5E, 0x5A, 0x46, 0x42, 0x4E, 0x4A
+.byte 0xB6, 0xB2, 0xBE, 0xBA, 0xA6, 0xA2, 0xAE, 0xAA
+.byte 0x96, 0x92, 0x9E, 0x9A, 0x86, 0x82, 0x8E, 0x8A
+.byte 0xF6, 0xF2, 0xFE, 0xFA, 0xE6, 0xE2, 0xEE, 0xEA
+.byte 0xD6, 0xD2, 0xDE, 0xDA, 0xC6, 0xC2, 0xCE, 0xCA
+.byte 0x2D, 0x29, 0x25, 0x21, 0x3D, 0x39, 0x35, 0x31
+.byte 0x0D, 0x09, 0x05, 0x01, 0x1D, 0x19, 0x15, 0x11
+.byte 0x6D, 0x69, 0x65, 0x61, 0x7D, 0x79, 0x75, 0x71
+.byte 0x4D, 0x49, 0x45, 0x41, 0x5D, 0x59, 0x55, 0x51
+.byte 0xAD, 0xA9, 0xA5, 0xA1, 0xBD, 0xB9, 0xB5, 0xB1
+.byte 0x8D, 0x89, 0x85, 0x81, 0x9D, 0x99, 0x95, 0x91
+.byte 0xED, 0xE9, 0xE5, 0xE1, 0xFD, 0xF9, 0xF5, 0xF1
+.byte 0xCD, 0xC9, 0xC5, 0xC1, 0xDD, 0xD9, 0xD5, 0xD1
+
--- /dev/null
+/* aes_dec.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes_dec.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-30
+ * \license GPLv3 or later
+ *
+ */
+#ifndef AES_DEC_H_
+#define AES_DEC_H_
+#include "aes_types.h"
+#include <stdint.h>
+
+
+void aes_decrypt_core(aes_cipher_state_t* state,const aes_genctx_t* ks, uint8_t rounds);
+
+
+#endif
--- /dev/null
+/* aes_enc-asm.S */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008, 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes_enc-asm.S
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-10
+ * \license GPLv3 or later
+ *
+ */
+
+#include "avr-asm-macros.S"
+
+
+/*
+ * param a: r24
+ * param b: r22
+ * param reducer: r0
+ */
+A = 28
+B = 29
+P = 0
+xREDUCER = 25
+
+.global aes256_enc
+aes256_enc:
+ ldi r20, 14
+ rjmp aes_encrypt_core
+
+.global aes192_enc
+aes192_enc:
+ ldi r20, 12
+ rjmp aes_encrypt_core
+
+.global aes128_enc
+aes128_enc:
+ ldi r20, 10
+
+
+/*
+ void aes_encrypt_core(aes_cipher_state_t* state, const aes_genctx_t* ks, uint8_t rounds)
+*/
+T0= 2
+T1= 3
+T2= 4
+T3= 5
+SBOX_SAVE0 = 6
+SBOX_SAVE1 = 7
+ST00 = 8
+ST01 = 9
+ST02 = 10
+ST03 = 11
+ST10 = 12
+ST11 = 13
+ST12 = 14
+ST13 = 15
+ST20 = 16
+ST21 = 17
+ST22 = 18
+ST23 = 19
+ST30 = 20
+ST31 = 21
+ST32 = 22
+ST33 = 23
+CTR = 24
+/*
+ * param state: r24:r25
+ * param ks: r22:r23
+ * param rounds: r20
+ */
+.global aes_encrypt_core
+aes_encrypt_core:
+ push_range 2, 17
+ push r28
+ push r29
+ push r24
+ push r25
+ movw r26, r22
+ movw r30, r24
+ mov CTR, r20
+ clt
+
+ .irp param,ST00, ST01, ST02, ST03, ST10, ST11, ST12, ST13, ST20, ST21, ST22, ST23, ST30, ST31, ST32, ST33
+ ld \param, Z+
+ .endr
+
+ ldi xREDUCER, 0x1b /* load reducer */
+ ldi r31, hi8(aes_sbox)
+
+ /* key whitening */
+1:
+ .irp param,ST00, ST01, ST02, ST03, ST10, ST11, ST12, ST13, ST20, ST21, ST22, ST23, ST30, ST31, ST32, ST33
+ ld r0, X+
+ eor \param, r0
+ .endr
+
+ brtc 2f
+exit:
+ pop r31
+ pop r30
+ st Z+, ST00
+ st Z+, ST01
+ st Z+, ST02
+ st Z+, ST03
+ st Z+, ST10
+ st Z+, ST11
+ st Z+, ST12
+ st Z+, ST13
+ st Z+, ST20
+ st Z+, ST21
+ st Z+, ST22
+ st Z+, ST23
+ st Z+, ST30
+ st Z+, ST31
+ st Z+, ST32
+ st Z+, ST33
+ pop r29
+ pop r28
+ pop_range 2, 17
+ ret
+
+2: dec CTR
+ brne 3f
+ set
+3:
+
+ /* encryption loop */
+
+ /* SBOX substitution and shifting */
+ mov r30, ST00
+ lpm ST00, Z
+ mov r30, ST10
+ lpm ST10, Z
+ mov r30, ST20
+ lpm ST20, Z
+ mov r30, ST30
+ lpm ST30, Z
+
+ mov r30, ST01
+ lpm T0, Z
+ mov r30, ST11
+ lpm ST01, Z
+ mov r30, ST21
+ lpm ST11, Z
+ mov r30, ST31
+ lpm ST21, Z
+ mov ST31, T0
+
+ mov r30, ST02
+ lpm T0, Z
+ mov r30, ST12
+ lpm T1, Z
+ mov r30, ST22
+ lpm ST02, Z
+ mov r30, ST32
+ lpm ST12, Z
+ mov ST22, T0
+ mov ST32, T1
+
+ mov r30, ST03
+ lpm T0, Z
+ mov r30, ST33
+ lpm ST03, Z
+ mov r30, ST23
+ lpm ST33, Z
+ mov r30, ST13
+ lpm ST23, Z
+ mov ST13, T0
+
+ /* mixcols (or rows in our case) */
+ brtc 2f
+ rjmp 1b
+2:
+ /* mixrow 1 */
+ mov r0, ST02
+ eor r0, ST03
+ mov T2, r0
+
+ mov T0, ST00
+ eor ST00, ST01
+ eor r0, ST00
+ lsl ST00
+ brcc 3f
+ eor ST00, xREDUCER
+3: eor ST00, r0
+ eor ST00, T0
+
+ mov T1, ST01
+ eor T1, ST02
+ lsl T1
+ brcc 3f
+ eor T1, xREDUCER
+3: eor T1, r0
+ eor ST01, T1
+
+ lsl T2
+ brcc 3f
+ eor T2, xREDUCER
+3: eor T2, r0
+ eor ST02, T2
+
+ eor T0, ST03
+ lsl T0
+ brcc 3f
+ eor T0, xREDUCER
+3: eor T0, r0
+ eor ST03, T0
+
+ /* mixrow 2 */
+ mov r0, ST12
+ eor r0, ST13
+ mov T2, r0
+
+ mov T0, ST10
+ eor ST10, ST11
+ eor r0, ST10
+ lsl ST10
+ brcc 3f
+ eor ST10, xREDUCER
+3: eor ST10, r0
+ eor ST10, T0
+
+ mov T1, ST11
+ eor T1, ST12
+ lsl T1
+ brcc 3f
+ eor T1, xREDUCER
+3: eor T1, r0
+ eor ST11, T1
+
+ lsl T2
+ brcc 3f
+ eor T2, xREDUCER
+3: eor T2, r0
+ eor ST12, T2
+
+ eor T0, ST13
+ lsl T0
+ brcc 3f
+ eor T0, xREDUCER
+3: eor T0, r0
+ eor ST13, T0
+
+ /* mixrow 3 */
+ mov r0, ST22
+ eor r0, ST23
+ mov T2, r0
+
+ mov T0, ST20
+ eor ST20, ST21
+ eor r0, ST20
+ lsl ST20
+ brcc 3f
+ eor ST20, xREDUCER
+3: eor ST20, r0
+ eor ST20, T0
+
+ mov T1, ST21
+ eor T1, ST22
+ lsl T1
+ brcc 3f
+ eor T1, xREDUCER
+3: eor T1, r0
+ eor ST21, T1
+
+ lsl T2
+ brcc 3f
+ eor T2, xREDUCER
+3: eor T2, r0
+ eor ST22, T2
+
+ eor T0, ST23
+ lsl T0
+ brcc 3f
+ eor T0, xREDUCER
+3: eor T0, r0
+ eor ST23, T0
+
+ /* mixrow 4 */
+ mov r0, ST32
+ eor r0, ST33
+ mov T2, r0
+
+ mov T0, ST30
+ eor ST30, ST31
+ eor r0, ST30
+ lsl ST30
+ brcc 3f
+ eor ST30, xREDUCER
+3: eor ST30, r0
+ eor ST30, T0
+
+ mov T1, ST31
+ eor T1, ST32
+ lsl T1
+ brcc 3f
+ eor T1, xREDUCER
+3: eor T1, r0
+ eor ST31, T1
+
+ lsl T2
+ brcc 3f
+ eor T2, xREDUCER
+3: eor T2, r0
+ eor ST32, T2
+
+ eor T0, ST33
+ lsl T0
+ brcc 3f
+ eor T0, xREDUCER
+3: eor T0, r0
+ eor ST33, T0
+ /* mix colums (rows) done */
+
+ /* add key*/
+ rjmp 1b
+
+
+
+
+
+
+
+
+
--- /dev/null
+/* aes_enc.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes_enc.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-30
+ * \license GPLv3 or later
+ *
+ */
+#ifndef AES_ENC_H_
+#define AES_ENC_H_
+#include "aes_types.h"
+#include <stdint.h>
+
+
+void aes_encrypt_core(aes_cipher_state_t* state, const aes_genctx_t* ks, uint8_t rounds);
+
+
+#endif
--- /dev/null
+/* aes_sbox-asm.S */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008, 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes_dec-asm.S
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-10
+ * \license GPLv3 or later
+ *
+ */
+.balign 256
+.global aes_invsbox
+aes_invsbox:
+.byte 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb
+.byte 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb
+.byte 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e
+.byte 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25
+.byte 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92
+.byte 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84
+.byte 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06
+.byte 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b
+.byte 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73
+.byte 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e
+.byte 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b
+.byte 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4
+.byte 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f
+.byte 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef
+.byte 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61
+.byte 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
--- /dev/null
+/* aes_invsbox.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes_invsbox.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-30
+ * \license GPLv3 or later
+ *
+ */
+#ifndef AES_INVSBOX_H_
+#define AES_INVSBOX_H_
+#include <stdint.h>
+
+extern uint8_t aes_invsbox[];
+
+#endif
--- /dev/null
+/* aes_keyschedule-asm */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008, 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes_keyschedule-asm.S
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-09
+ * \license GPLv3 or later
+ *
+ */
+
+#include "avr-asm-macros.S"
+
+.global aes256_init
+aes256_init:
+ movw r20, r22
+ ldi r23, hi8(256)
+ ldi r22, lo8(256)
+ rjmp aes_init
+
+.global aes192_init
+aes192_init:
+ movw r20, r22
+ ldi r23, hi8(192)
+ ldi r22, lo8(192)
+ rjmp aes_init
+
+.global aes128_init
+aes128_init:
+ movw r20, r22
+ clr r23
+ ldi r22, 128
+
+/*
+void aes_init(const void* key, uint16_t keysize_b, aes_genctx_t* ctx){
+ uint8_t hi,i,nk, next_nk;
+ uint8_t rc=1;
+ uint8_t tmp[4];
+ nk=keysize_b>>5; / * 4, 6, 8 * /
+ hi=4*(nk+6+1);
+ memcpy(ctx, key, keysize_b/8);
+ next_nk = nk;
+ for(i=nk;i<hi;++i){
+ *((uint32_t*)tmp) = ((uint32_t*)(ctx->key[0].ks))[i-1];
+ if(i!=next_nk){
+ if(nk==8 && i%8==4){
+ tmp[0] = pgm_read_byte(aes_sbox+tmp[0]);
+ tmp[1] = pgm_read_byte(aes_sbox+tmp[1]);
+ tmp[2] = pgm_read_byte(aes_sbox+tmp[2]);
+ tmp[3] = pgm_read_byte(aes_sbox+tmp[3]);
+ }
+ } else {
+ next_nk += nk;
+ aes_rotword(tmp);
+ tmp[0] = pgm_read_byte(aes_sbox+tmp[0]);
+ tmp[1] = pgm_read_byte(aes_sbox+tmp[1]);
+ tmp[2] = pgm_read_byte(aes_sbox+tmp[2]);
+ tmp[3] = pgm_read_byte(aes_sbox+tmp[3]);
+ tmp[0] ^= rc;
+ rc<<=1;
+ }
+ ((uint32_t*)(ctx->key[0].ks))[i] = ((uint32_t*)(ctx->key[0].ks))[i-nk]
+ ^ *((uint32_t*)tmp);
+ }
+}
+*/
+
+SBOX_SAVE0 = 14
+SBOX_SAVE1 = 15
+XRC = 17
+NK = 22
+C1 = 18
+NEXT_NK = 19
+HI = 23
+T0 = 20
+T1 = 21
+T2 = 24
+T3 = 25
+/*
+ * param key: r24:r25
+ * param keysize_b: r22:r23
+ * param ctx: r20:r21
+ */
+.global aes_init
+aes_init:
+ push_range 14, 17
+ push r28
+ push r29
+ movw r30, r20
+ movw r28, r20
+ movw r26, r24
+ lsr r23
+ ror r22
+ lsr r22
+ lsr r22 /* r22 contains keysize_b/8 */
+ mov C1, r22
+
+1: /* copy key to ctx */
+ ld r0, X+
+ st Z+, r0
+ dec C1
+ brne 1b
+
+ lsr NK
+ lsr NK
+ bst NK,3 /* set T if NK==8 */
+ mov NEXT_NK, NK
+ mov HI, NK
+ subi HI, -7
+ lsl HI
+ lsl HI
+ movw r26, r30
+ sbiw r26, 4
+ mov C1, NK
+ ldi r30, lo8(aes_sbox)
+ ldi r31, hi8(aes_sbox)
+ movw SBOX_SAVE0, r30
+ ldi XRC, 1
+1:
+ ld T0, X+
+ ld T1, X+
+ ld T2, X+
+ ld T3, X+
+ cp NEXT_NK, C1
+ breq 2f
+ brtc 5f
+ mov r16, C1
+ andi r16, 0x07
+ cpi r16, 0x04
+ brne 5f
+ movw r30, SBOX_SAVE0
+ add r30, T0
+ adc r31, r1
+ lpm T0, Z
+ movw r30, SBOX_SAVE0
+ add r30, T1
+ adc r31, r1
+ lpm T1, Z
+ movw r30, SBOX_SAVE0
+ add r30, T2
+ adc r31, r1
+ lpm T2, Z
+ movw r30, SBOX_SAVE0
+ add r30, T3
+ adc r31, r1
+ lpm T3, Z
+ rjmp 5f
+2:
+ add NEXT_NK, NK
+ movw r30, SBOX_SAVE0
+ add r30, T0
+ adc r31, r1
+ lpm r16, Z
+ movw r30, SBOX_SAVE0
+ add r30, T1
+ adc r31, r1
+ lpm T0, Z
+ movw r30, SBOX_SAVE0
+ add r30, T2
+ adc r31, r1
+ lpm T1, Z
+ movw r30, SBOX_SAVE0
+ add r30, T3
+ adc r31, r1
+ lpm T2, Z
+ mov T3, r16
+ eor T0, XRC
+ lsl XRC
+ brcc 3f
+ ldi XRC, 0x1b
+3:
+5:
+ movw r30, r26
+
+ ld r0, Y+
+ eor r0, T0
+ st Z+, r0
+ ld r0, Y+
+ eor r0 ,T1
+ st Z+, r0
+ ld r0, Y+
+ eor r0, T2
+ st Z+, r0
+ ld r0, Y+
+ eor r0, T3
+ st Z+, r0
+
+/*
+ st Z+, T0
+ st Z+, T1
+ st Z+, T2
+ st Z+, T3
+*/
+
+ inc C1
+ cp C1, HI
+ breq 6f
+ rjmp 1b
+6:
+
+ clt
+ pop r29
+ pop r28
+ pop_range 14, 17
+ ret
+
+
+
+
--- /dev/null
+/* aes_keyschedule.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes_keyschedule.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-30
+ * \license GPLv3 or later
+ * \ingroup AES
+ */
+
+
+#ifndef AES_KEYSCHEDULE_H_
+#define AES_KEYSCHEDULE_H_
+
+#include "aes_types.h"
+/**
+ * \brief initialize the keyschedule
+ *
+ * This function computes the keyschedule from a given key with a given length
+ * and stores it in the context variable
+ * \param key pointer to the key material
+ * \param keysize_b length of the key in bits (valid are 128, 192 and 256)
+ * \param ctx pointer to the context where the keyschedule should be stored
+ */
+void aes_init(const void* key, uint16_t keysize_b, aes_genctx_t* ctx);
+
+/**
+ * \brief initialize the keyschedule for 128 bit key
+ *
+ * This function computes the keyschedule from a given 128 bit key
+ * and stores it in the context variable
+ * \param key pointer to the key material
+ * \param ctx pointer to the context where the keyschedule should be stored
+ */
+void aes128_init(const void* key, aes128_ctx_t* ctx);
+
+/**
+ * \brief initialize the keyschedule for 192 bit key
+ *
+ * This function computes the keyschedule from a given 192 bit key
+ * and stores it in the context variable
+ * \param key pointer to the key material
+ * \param ctx pointer to the context where the keyschedule should be stored
+ */
+void aes192_init(const void* key, aes192_ctx_t* ctx);
+
+/**
+ * \brief initialize the keyschedule for 256 bit key
+ *
+ * This function computes the keyschedule from a given 256 bit key
+ * and stores it in the context variable
+ * \param key pointer to the key material
+ * \param ctx pointer to the context where the keyschedule should be stored
+ */
+void aes256_init(const void* key, aes256_ctx_t* ctx);
+
+#endif /* AES_KEYSCHEDULE_H_ */
+
--- /dev/null
+/* aes_sbox-asm.S */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008, 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes_dec-asm.S
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-10
+ * \license GPLv3 or later
+ *
+ */
+
+.balign 256
+.global aes_sbox
+aes_sbox:
+.byte 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76
+.byte 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0
+.byte 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15
+.byte 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75
+.byte 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84
+.byte 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf
+.byte 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8
+.byte 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2
+.byte 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73
+.byte 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb
+.byte 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79
+.byte 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08
+.byte 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a
+.byte 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e
+.byte 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf
+.byte 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
+
--- /dev/null
+/* aes_sbox.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes_sbox.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-30
+ * \license GPLv3 or later
+ *
+ */
+#ifndef AES_SBOX_H_
+#define AES_SBOX_H_
+#include <stdint.h>
+
+extern uint8_t aes_sbox[];
+
+#endif
--- /dev/null
+/* aes.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes_types.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-30
+ * \license GPLv3 or later
+ *
+ */
+#ifndef AES_TYPES_H_
+#define AES_TYPES_H_
+
+#include <stdint.h>
+
+typedef struct{
+ uint8_t ks[16];
+} aes_roundkey_t;
+
+typedef struct{
+ aes_roundkey_t key[10+1];
+} aes128_ctx_t;
+
+typedef struct{
+ aes_roundkey_t key[12+1];
+} aes192_ctx_t;
+
+typedef struct{
+ aes_roundkey_t key[14+1];
+} aes256_ctx_t;
+
+typedef struct{
+ aes_roundkey_t key[1]; /* just to avoid the warning */
+} aes_genctx_t;
+
+typedef struct{
+ uint8_t s[16];
+} aes_cipher_state_t;
+
+#endif
--- /dev/null
+/* avr-asm-macros.S */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * File: avr-asm-macros.S
+ * Author: Daniel Otte
+ * Date: 2008-08-13
+ * License: GPLv3 or later
+ * Description: some macros which are quite usefull
+ *
+ */
+
+//#ifndef AVR_ASM_MACROS__S__
+//#define AVR_ASM_MACROS__S__
+//#include <avr/io.h>
+
+/*******************************************************************************
+* MACRO SECTION *
+*******************************************************************************/
+
+.macro push_ p1:req, p2:vararg
+ push \p1
+.ifnb \p2
+ push_ \p2
+.endif
+.endm
+
+.macro pop_ p1:req, p2:vararg
+ pop \p1
+.ifnb \p2
+ pop_ \p2
+.endif
+.endm
+
+.macro push_range from:req, to:req
+ push \from
+.if \to-\from
+ push_range "(\from+1)",\to
+.endif
+.endm
+
+.macro pop_range from:req, to:req
+ pop \to
+.if \to-\from
+ pop_range \from,"(\to-1)"
+.endif
+.endm
+
+.macro stack_alloc size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ sbiw \reg1, \size
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+.macro stack_free size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ adiw \reg1, \size
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+
+.macro stack_alloc_large size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ subi \reg1, lo8(\size)
+ sbci \reg2, hi8(\size)
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+.macro stack_free_large size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ adiw \reg1, 63
+ adiw \reg1, (\size-63)
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+.macro stack_free_large2 size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ adiw \reg1, 63
+ adiw \reg1, 63
+ adiw \reg1, (\size-63*2)
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+.macro stack_free_large3 size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ push r16
+ push r17
+ ldi r16, lo8(\size)
+ ldi r17, hi8(\size)
+ add \reg1, r16
+ adc \reg2, r17
+ pop r17
+ pop r16
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+
+/*******************************************************************************
+* END of MACRO SECTION *
+*******************************************************************************/
+
+
+//#endif /* AVR_ASM_MACROS__S__ */
+
--- /dev/null
+/* avr-asm-macros.S */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * File: avr-asm-macros.S
+ * Author: Daniel Otte
+ * Date: 2008-08-13
+ * License: GPLv3 or later
+ * Description: some macros which are quite usefull
+ *
+ */
+
+//#ifndef AVR_ASM_MACROS__S__
+//#define AVR_ASM_MACROS__S__
+#include <avr/io.h>
+
+/*******************************************************************************
+* MACRO SECTION *
+*******************************************************************************/
+
+.macro push_ p1:req, p2:vararg
+ push \p1
+.ifnb \p2
+ push_ \p2
+.endif
+.endm
+
+.macro pop_ p1:req, p2:vararg
+ pop \p1
+.ifnb \p2
+ pop_ \p2
+.endif
+.endm
+
+.macro push_range from:req, to:req
+ push \from
+.if \to-\from
+ push_range "(\from+1)",\to
+.endif
+.endm
+
+.macro pop_range from:req, to:req
+ pop \to
+.if \to-\from
+ pop_range \from,"(\to-1)"
+.endif
+.endm
+
+.macro stack_alloc size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ sbiw \reg1, \size
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+.macro stack_free size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ adiw \reg1, \size
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+
+.macro stack_alloc_large size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ subi \reg1, lo8(\size)
+ sbci \reg2, hi8(\size)
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+.macro stack_free_large size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ adiw \reg1, 63
+ adiw \reg1, (\size-63)
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+.macro stack_free_large2 size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ adiw \reg1, 63
+ adiw \reg1, 63
+ adiw \reg1, (\size-63*2)
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+.macro stack_free_large3 size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ push r16
+ push r17
+ ldi r16, lo8(\size)
+ ldi r17, hi8(\size)
+ add \reg1, r16
+ adc \reg2, r17
+ pop r17
+ pop r16
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+
+/*******************************************************************************
+* END of MACRO SECTION *
+*******************************************************************************/
+
+
+//#endif /* AVR_ASM_MACROS__S__ */
+
--- /dev/null
+/* bcal-basic.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#if (defined(__AVR__))
+#include <avr\pgmspace.h>
+#else
+#include <pgmspace.h>
+#endif
+#include "blockcipher_descriptor.h"
+#include "keysize_descriptor.h"
+
+uint8_t bcal_cipher_init(const bcdesc_t* cipher_descriptor,
+ const void* key, uint16_t keysize_b, bcgen_ctx_t* ctx){
+ if(!is_valid_keysize_P((PGM_VOID_P)pgm_read_word(&(cipher_descriptor->valid_keysize_desc)),
+ keysize_b)){
+ return 1;
+ }
+ uint8_t flags;
+ bc_init_fpt init_fpt;
+ ctx->desc_ptr = (bcdesc_t*)cipher_descriptor;
+ ctx->keysize = keysize_b;
+ flags = pgm_read_byte(cipher_descriptor->flags);
+ init_fpt.initvoid = (void_fpt)(pgm_read_word(&(cipher_descriptor->init.initvoid)));
+ if(init_fpt.initvoid == NULL){
+ if(!(ctx->ctx = malloc((keysize_b+7)/8)))
+ return 2;
+ memcpy(ctx->ctx, key, (keysize_b+7)/8);
+ return 0;
+ }
+ if(!(ctx->ctx = malloc(pgm_read_word(&(cipher_descriptor->ctxsize_B)))))
+ return 3;
+ if((flags&BC_INIT_TYPE)==BC_INIT_TYPE_1){
+ init_fpt.init1((void*)key, (ctx->ctx));
+ }else{
+ init_fpt.init2((void*)key, keysize_b, (ctx->ctx));
+ }
+ return 0;
+}
+
+void bcal_cipher_free(bcgen_ctx_t* ctx){
+ if(!ctx)
+ return;
+ bc_free_fpt free_fpt;
+ free_fpt = (bc_free_fpt)(pgm_read_word(&(ctx->desc_ptr->free)));
+ if(free_fpt)
+ free_fpt((ctx->ctx));
+ free(ctx->ctx);
+}
+
+void bcal_cipher_enc(void* block, const bcgen_ctx_t* ctx){
+ bc_enc_fpt enc_fpt;
+ enc_fpt.encvoid = (void_fpt)pgm_read_word(&(ctx->desc_ptr->enc.encvoid));
+ if(!enc_fpt.encvoid){
+ /* very bad error, no enciphering function specified */
+ return;
+ }
+ enc_fpt.enc1(block, (ctx->ctx));
+
+}
+
+void bcal_cipher_dec(void* block, const bcgen_ctx_t* ctx){
+ bc_dec_fpt dec_fpt;
+ dec_fpt.decvoid = (void_fpt)pgm_read_word(&(ctx->desc_ptr->dec.decvoid));
+ if(!dec_fpt.decvoid){
+ /* very bad error, no deciphering function specified */
+ return;
+ }
+ dec_fpt.dec1(block, (ctx->ctx));
+}
+
+uint16_t bcal_cipher_getBlocksize_b(const bcdesc_t* desc){
+ return pgm_read_word(&(desc->blocksize_b));
+}
+
+PGM_VOID_P bcal_cipher_getKeysizeDesc(const bcdesc_t* desc){
+ return (PGM_VOID_P)pgm_read_word(&(desc->valid_keysize_desc));
+}
+
+
--- /dev/null
+/* bcal-basic.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <avr/pgmspace.h>
+#include "blockcipher_descriptor.h"
+#include "keysize_descriptor.h"
+
+uint8_t bcal_cipher_init(const bcdesc_t* cipher_descriptor,
+ const void* key, uint16_t keysize_b, bcgen_ctx_t* ctx){
+ if(!is_valid_keysize_P((PGM_VOID_P)pgm_read_word(&(cipher_descriptor->valid_keysize_desc)),
+ keysize_b)){
+ return 1;
+ }
+ uint8_t flags;
+ bc_init_fpt init_fpt;
+ ctx->desc_ptr = (bcdesc_t*)cipher_descriptor;
+ ctx->keysize = keysize_b;
+ flags = pgm_read_byte(cipher_descriptor->flags);
+ init_fpt.initvoid = (void_fpt)(pgm_read_word(&(cipher_descriptor->init.initvoid)));
+ if(init_fpt.initvoid == NULL){
+ if(!(ctx->ctx = malloc((keysize_b+7)/8)))
+ return 2;
+ memcpy(ctx->ctx, key, (keysize_b+7)/8);
+ return 0;
+ }
+ if(!(ctx->ctx = malloc(pgm_read_word(&(cipher_descriptor->ctxsize_B)))))
+ return 3;
+ if((flags&BC_INIT_TYPE)==BC_INIT_TYPE_1){
+ init_fpt.init1((void*)key, (ctx->ctx));
+ }else{
+ init_fpt.init2((void*)key, keysize_b, (ctx->ctx));
+ }
+ return 0;
+}
+
+void bcal_cipher_free(bcgen_ctx_t* ctx){
+ if(!ctx)
+ return;
+ bc_free_fpt free_fpt;
+ free_fpt = (bc_free_fpt)(pgm_read_word(&(ctx->desc_ptr->free)));
+ if(free_fpt)
+ free_fpt((ctx->ctx));
+ free(ctx->ctx);
+}
+
+void bcal_cipher_enc(void* block, const bcgen_ctx_t* ctx){
+ bc_enc_fpt enc_fpt;
+ enc_fpt.encvoid = (void_fpt)pgm_read_word(&(ctx->desc_ptr->enc.encvoid));
+ if(!enc_fpt.encvoid){
+ /* very bad error, no enciphering function specified */
+ return;
+ }
+ enc_fpt.enc1(block, (ctx->ctx));
+
+}
+
+void bcal_cipher_dec(void* block, const bcgen_ctx_t* ctx){
+ bc_dec_fpt dec_fpt;
+ dec_fpt.decvoid = (void_fpt)pgm_read_word(&(ctx->desc_ptr->dec.decvoid));
+ if(!dec_fpt.decvoid){
+ /* very bad error, no deciphering function specified */
+ return;
+ }
+ dec_fpt.dec1(block, (ctx->ctx));
+}
+
+uint16_t bcal_cipher_getBlocksize_b(const bcdesc_t* desc){
+ return pgm_read_word(&(desc->blocksize_b));
+}
+
+PGM_VOID_P bcal_cipher_getKeysizeDesc(const bcdesc_t* desc){
+ return (PGM_VOID_P)pgm_read_word(&(desc->valid_keysize_desc));
+}
+
+
--- /dev/null
+/* bcal-basic.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef BCAL_BASIC_H_
+#define BCAL_BASIC_H_
+
+#include <stdlib.h>
+#include <stdint.h>
+#include "blockcipher_descriptor.h"
+#include "keysize_descriptor.h"
+#if (defined(__AVR__))
+#include <avr\pgmspace.h>
+#else
+#include <pgmspace.h>
+#endif
+
+uint8_t bcal_cipher_init(const bcdesc_t* cipher_descriptor,
+ const void* key, uint16_t keysize_b, bcgen_ctx_t* ctx);
+void bcal_cipher_free(bcgen_ctx_t* ctx);
+void bcal_cipher_enc(void* block, const bcgen_ctx_t* ctx);
+void bcal_cipher_dec(void* block, const bcgen_ctx_t* ctx);
+uint16_t bcal_cipher_getBlocksize_b(const bcdesc_t* desc);
+PGM_VOID_P bcal_cipher_getKeysizeDesc(const bcdesc_t* desc);
+#endif /* BCAL_BASIC_H_ */
--- /dev/null
+/* bcal-basic.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef BCAL_BASIC_H_
+#define BCAL_BASIC_H_
+
+#include <stdlib.h>
+#include <stdint.h>
+#include "blockcipher_descriptor.h"
+#include "keysize_descriptor.h"
+#include <avr/pgmspace.h>
+
+uint8_t bcal_cipher_init(const bcdesc_t* cipher_descriptor,
+ const void* key, uint16_t keysize_b, bcgen_ctx_t* ctx);
+void bcal_cipher_free(bcgen_ctx_t* ctx);
+void bcal_cipher_enc(void* block, const bcgen_ctx_t* ctx);
+void bcal_cipher_dec(void* block, const bcgen_ctx_t* ctx);
+uint16_t bcal_cipher_getBlocksize_b(const bcdesc_t* desc);
+PGM_VOID_P bcal_cipher_getKeysizeDesc(const bcdesc_t* desc);
+#endif /* BCAL_BASIC_H_ */
--- /dev/null
+/* bcal-cbc.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2010 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+#include <string.h>
+#include "bcal-cbc.h"
+#include "bcal-basic.h"
+#include "memxor.h"
+
+uint8_t bcal_cbc_init(const bcdesc_t* desc, const void* key, uint16_t keysize_b, bcal_cbc_ctx_t* ctx){
+ ctx->desc = (bcdesc_t*)desc;
+ ctx->blocksize_B = (bcal_cipher_getBlocksize_b(desc)+7)/8;
+ ctx->prev_block = malloc(ctx->blocksize_B);
+
+ if(ctx->prev_block==NULL){
+ return 0x11;
+ }
+ return bcal_cipher_init(desc, key, keysize_b, &(ctx->cctx));
+}
+
+void bcal_cbc_free(bcal_cbc_ctx_t* ctx){
+ bcal_cipher_free(&(ctx->cctx));
+ free(ctx->prev_block);
+}
+
+
+void bcal_cbc_loadIV(const void* iv, bcal_cbc_ctx_t* ctx){
+ if(iv){
+ memcpy(ctx->prev_block, iv, ctx->blocksize_B);
+ }
+}
+
+void bcal_cbc_encNext(void* block, bcal_cbc_ctx_t* ctx){
+ memxor(block, ctx->prev_block, ctx->blocksize_B);
+ bcal_cipher_enc(block, &(ctx->cctx));
+ memcpy(ctx->prev_block, block, ctx->blocksize_B);
+}
+
+void bcal_cbc_decNext(void* block, bcal_cbc_ctx_t* ctx){
+ uint8_t tmp[ctx->blocksize_B];
+ memcpy(tmp, block, ctx->blocksize_B);
+ bcal_cipher_dec(block, &(ctx->cctx));
+ memxor(block, ctx->prev_block, ctx->blocksize_B);
+ memcpy(ctx->prev_block, tmp, ctx->blocksize_B);
+}
+void bcal_cbc_decRand(void* block, const void* prev_block, bcal_cbc_ctx_t* ctx){
+ bcal_cipher_dec(block, &(ctx->cctx));
+ memxor(block, prev_block, ctx->blocksize_B);
+}
+
+void bcal_cbc_encMsg(const void* iv, void* msg, uint16_t msg_blocks, bcal_cbc_ctx_t* ctx){
+ bcal_cbc_loadIV(iv, ctx);
+ while(msg_blocks--){
+ bcal_cbc_encNext(msg, ctx);
+ msg = (uint8_t*)msg + ctx->blocksize_B;
+ }
+}
+
+void bcal_cbc_decMsg(const void* iv, void* msg, uint16_t msg_blocks, bcal_cbc_ctx_t* ctx){
+ msg=(uint8_t*)msg + (msg_blocks-1)*ctx->blocksize_B;
+ while(msg_blocks > 1){
+ bcal_cbc_decRand(msg, (uint8_t*)msg-ctx->blocksize_B, ctx);
+ msg_blocks -= 1;
+ msg=(uint8_t*)msg-ctx->blocksize_B;
+ }
+ bcal_cbc_decRand(msg, iv, ctx);
+}
+
--- /dev/null
+/* bcal-cbc.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2010 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef BCALCBC_H_
+#define BCALCBC_H_
+
+#include <stdint.h>
+#include "blockcipher_descriptor.h"
+#include "bcal-basic.h"
+
+typedef struct{
+ bcdesc_t* desc;
+ bcgen_ctx_t cctx;
+ uint8_t* prev_block;
+ uint8_t blocksize_B;
+} bcal_cbc_ctx_t;
+
+uint8_t bcal_cbc_init(const bcdesc_t* desc, const void* key, uint16_t keysize_b, bcal_cbc_ctx_t* ctx);
+void bcal_cbc_free(bcal_cbc_ctx_t* ctx);
+void bcal_cbc_loadIV(const void* iv, bcal_cbc_ctx_t* ctx);
+void bcal_cbc_encNext(void* block, bcal_cbc_ctx_t* ctx);
+void bcal_cbc_decNext(void* block, bcal_cbc_ctx_t* ctx);
+void bcal_cbc_decRand(void* block, const void* prev_block, bcal_cbc_ctx_t* ctx);
+void bcal_cbc_encMsg(const void* iv, void* msg, uint16_t msg_blocks, bcal_cbc_ctx_t* ctx);
+void bcal_cbc_decMsg(const void* iv, void* msg, uint16_t msg_blocks, bcal_cbc_ctx_t* ctx);
+
+
+#endif /* BCALCBC_H_ */
--- /dev/null
+/* bcal-omac.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2010 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#include <stdint.h>
+#include <string.h>
+#include "bcal-basic.h"
+#include "bcal-cmac.h"
+#include "memxor.h"
+
+
+static uint8_t left_shift_be_block(void* block, uint8_t blocksize_B){
+ uint8_t c1=0, c2;
+ do{
+ --blocksize_B;
+ c2 = (((uint8_t*)block)[blocksize_B])>>7;
+ (((uint8_t*)block)[blocksize_B]) <<= 1;
+ (((uint8_t*)block)[blocksize_B]) |= c1;
+ c1 = c2;
+ }while(blocksize_B);
+ return c1;
+}
+
+static const uint8_t const_128 = 0x87;
+static const uint8_t const_64 = 0x1b;
+
+uint8_t bcal_cmac_init(const bcdesc_t* desc, const void* key, uint16_t keysize_b, bcal_cmac_ctx_t* ctx){
+ uint8_t r;
+ ctx->desc = (bcdesc_t*)desc;
+ ctx->blocksize_B = bcal_cipher_getBlocksize_b(desc)/8;
+ if (ctx->blocksize_B!=128/8 && ctx->blocksize_B!=64/8){
+ return 0x13;
+ }
+ ctx->accu = malloc(ctx->blocksize_B);
+ if(ctx->accu==NULL){
+ return 0x14;
+ }
+ ctx->k1 = malloc(ctx->blocksize_B);
+ if(ctx->k1==NULL){
+ return 0x15;
+ }
+ ctx->k2 = malloc(ctx->blocksize_B);
+ if(ctx->k2==NULL){
+ return 0x16;
+ }
+ ctx->lastblock = malloc(ctx->blocksize_B);
+ if(ctx->lastblock==NULL){
+ return 0x17;
+ }
+ r = bcal_cipher_init(desc, key, keysize_b, &(ctx->cctx));
+ if(r){
+ return r;
+ }
+ if(ctx->blocksize_B==128/8){
+ r = const_128;
+ }else{
+ r = const_64;
+ }
+ /* subkey computation */
+ memset(ctx->accu, 0x00, ctx->blocksize_B);
+ memset(ctx->k1, 0x00, ctx->blocksize_B);
+ bcal_cipher_enc(ctx->k1, &(ctx->cctx));
+ if(left_shift_be_block(ctx->k1, ctx->blocksize_B)){
+ ctx->k1[ctx->blocksize_B-1] ^= r;
+ }
+ memcpy(ctx->k2, ctx->k1, ctx->blocksize_B);
+ if(left_shift_be_block(ctx->k2, ctx->blocksize_B)){
+ ctx->k2[ctx->blocksize_B-1] ^= r;
+ }
+ ctx->last_set=0;
+ return 0;
+}
+
+void bcal_cmac_free(bcal_cmac_ctx_t* ctx){
+ free(ctx->accu);
+ free(ctx->k1);
+ free(ctx->k2);
+ bcal_cipher_free(&(ctx->cctx));
+}
+
+void bcal_cmac_nextBlock (bcal_cmac_ctx_t* ctx, const void* block){
+ if(ctx->last_set){
+ memxor(ctx->accu, ctx->lastblock, ctx->blocksize_B);
+ bcal_cipher_enc(ctx->accu, &(ctx->cctx));
+ }
+ memcpy(ctx->lastblock, block, ctx->blocksize_B);
+ ctx->last_set=1;
+}
+
+
+void bcal_cmac_lastBlock(bcal_cmac_ctx_t* ctx, const void* block, uint16_t length_b){
+ uint16_t blocksize_b;
+ blocksize_b = ctx->blocksize_B*8;
+ while(length_b>=blocksize_b){
+ bcal_cmac_nextBlock(ctx, block);
+ block = (uint8_t*)block + ctx->blocksize_B;
+ length_b -= blocksize_b;
+ }
+ if(ctx->last_set==0){
+ memxor(ctx->accu, block, (length_b+7)/8);
+ memxor(ctx->accu, ctx->k2, ctx->blocksize_B);
+ ctx->accu[length_b/8] ^= 0x80>>(length_b&7);
+ }else{
+ if(length_b==0){
+ memxor(ctx->accu, ctx->lastblock, ctx->blocksize_B);
+ memxor(ctx->accu, ctx->k1, ctx->blocksize_B);
+ }else{
+ memxor(ctx->accu, ctx->lastblock, ctx->blocksize_B);
+ bcal_cipher_enc(ctx->accu, &(ctx->cctx));
+ memxor(ctx->accu, block, (length_b+7)/8);
+ memxor(ctx->accu, ctx->k2, ctx->blocksize_B);
+ ctx->accu[length_b/8] ^= 0x80>>(length_b&7);
+ }
+ }
+ bcal_cipher_enc(ctx->accu, &(ctx->cctx));
+}
+
+void bcal_cmac_ctx2mac(void* dest, uint16_t length_b, const bcal_cmac_ctx_t* ctx){
+ memcpy(dest, ctx->accu, length_b/8);
+ if(length_b&7){
+ ((uint8_t*)dest)[length_b/8] &= 0xff>>(length_b&7);
+ ((uint8_t*)dest)[length_b/8] |= (0xff00>>(length_b&7))&(ctx->accu[length_b/8]);
+ }
+}
+
+void bcal_cmac(void* dest, uint16_t out_length_b, const void* block, uint32_t length_b, bcal_cmac_ctx_t* ctx){
+ uint16_t blocksize_b;
+ blocksize_b = ctx->blocksize_B*8;
+ while(length_b>blocksize_b){
+ bcal_cmac_nextBlock(ctx, block);
+ block = (uint8_t*)block + ctx->blocksize_B;
+ length_b -= blocksize_b;
+ }
+ bcal_cmac_lastBlock(ctx, block, length_b);
+ bcal_cmac_ctx2mac(dest, out_length_b, ctx);
+}
--- /dev/null
+/* bcal-cmac.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2010 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef BCALCMAC_H_
+#define BCALCMAC_H_
+
+#include <stdint.h>
+#include "bcal-basic.h"
+#include "blockcipher_descriptor.h"
+
+typedef struct{
+ bcdesc_t* desc;
+ bcgen_ctx_t cctx;
+ uint8_t* accu;
+ uint8_t* k1;
+ uint8_t* k2;
+ uint8_t* lastblock;
+ uint8_t last_set;
+ uint8_t blocksize_B;
+} bcal_cmac_ctx_t;
+
+uint8_t bcal_cmac_init(const bcdesc_t* desc, const void* key, uint16_t keysize_b, bcal_cmac_ctx_t* ctx);
+void bcal_cmac_free(bcal_cmac_ctx_t* ctx);
+void bcal_cmac_nextBlock(bcal_cmac_ctx_t* ctx, const void* block);
+void bcal_cmac_lastBlock(bcal_cmac_ctx_t* ctx, const void* block, uint16_t length_b);
+void bcal_cmac_ctx2mac(void* dest, uint16_t length_b, const bcal_cmac_ctx_t* ctx);
+void bcal_cmac(void* dest, uint16_t out_length_b, const void* block, uint32_t length_b, bcal_cmac_ctx_t* ctx);
+
+#endif /* BCALCMAC_H_ */
--- /dev/null
+/* bcal-ofb.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2010 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+#include <string.h>
+#include "bcal-ofb.h"
+#include "bcal-basic.h"
+#include "memxor.h"
+
+
+uint8_t bcal_ofb_init(const bcdesc_t* desc, const void* key, uint16_t keysize_b, bcal_ofb_ctx_t* ctx){
+ ctx->desc = (bcdesc_t*)desc;
+ ctx->blocksize_B = (bcal_cipher_getBlocksize_b(desc)+7)/8;
+ ctx->in_block=malloc(ctx->blocksize_B);
+ if(ctx->in_block==NULL){
+ return 0x11;
+ }
+ return bcal_cipher_init(desc, key, keysize_b, &(ctx->cctx));
+}
+
+void bcal_ofb_free(bcal_ofb_ctx_t* ctx){
+ free(ctx->in_block);
+ bcal_cipher_free(&(ctx->cctx));
+}
+
+void bcal_ofb_loadIV(const void* iv, bcal_ofb_ctx_t* ctx){
+ if(iv){
+ memcpy(ctx->in_block, iv, ctx->blocksize_B);
+ }
+}
+
+void bcal_ofb_encNext(void* block, bcal_ofb_ctx_t* ctx){
+ bcal_cipher_enc(ctx->in_block , &(ctx->cctx));
+ memxor(block, ctx->in_block, ctx->blocksize_B);
+}
+
+void bcal_ofb_decNext(void* block, bcal_ofb_ctx_t* ctx){
+ bcal_cipher_enc(ctx->in_block , &(ctx->cctx));
+ memxor(block, ctx->in_block, ctx->blocksize_B);
+}
+
+
+void bcal_ofb_encMsg(const void* iv, void* msg, uint32_t msg_len_b, bcal_ofb_ctx_t* ctx){
+ uint16_t block_len_b;
+ block_len_b = ctx->blocksize_B*8;
+ bcal_ofb_loadIV(iv, ctx);
+ while(msg_len_b>block_len_b){
+ bcal_ofb_encNext(msg, ctx);
+ msg_len_b -= block_len_b;
+ msg = (uint8_t*)msg + ctx->blocksize_B;
+ }
+ bcal_cipher_enc(ctx->in_block, &(ctx->cctx));
+ ctx->in_block[msg_len_b/8] = 0xff00>>(msg_len_b&7);
+ memxor(msg, ctx->in_block, (msg_len_b+7)/8);
+}
+
+void bcal_ofb_decMsg(const void* iv, void* msg, uint32_t msg_len_b, bcal_ofb_ctx_t* ctx){
+ bcal_ofb_encMsg(iv, msg, msg_len_b, ctx);
+}
+
--- /dev/null
+/* bcal-ofb.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2010 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#ifndef BCALOFB_H_
+#define BCALOFB_H_
+
+#include <stdint.h>
+#include "bcal-basic.h"
+#include "blockcipher_descriptor.h"
+
+
+typedef struct{
+ bcdesc_t* desc;
+ bcgen_ctx_t cctx;
+ uint8_t* in_block;
+ uint8_t blocksize_B;
+} bcal_ofb_ctx_t;
+
+
+uint8_t bcal_ofb_init(const bcdesc_t* desc, const void* key, uint16_t keysize_b, bcal_ofb_ctx_t* ctx);
+void bcal_ofb_free(bcal_ofb_ctx_t* ctx);
+void bcal_ofb_loadIV(const void* iv, bcal_ofb_ctx_t* ctx);
+void bcal_ofb_encNext(void* block, bcal_ofb_ctx_t* ctx);
+void bcal_ofb_decNext(void* block, bcal_ofb_ctx_t* ctx);
+void bcal_ofb_encMsg(const void* iv, void* msg, uint32_t msg_len_b, bcal_ofb_ctx_t* ctx);
+void bcal_ofb_decMsg(const void* iv, void* msg, uint32_t msg_len_b, bcal_ofb_ctx_t* ctx);
+
+
+#endif /* BCALOFB_H_ */
--- /dev/null
+/* bcal_aes128.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file bcal_aes128.c
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-08
+ * \license GPLv3 or later
+ *
+ */
+
+#if (defined(__AVR__))
+#include <avr\pgmspace.h>
+#else
+#include <pgmspace.h>
+#endif
+#include <stdlib.h>
+#include "blockcipher_descriptor.h"
+#include "aes.h"
+#include "aes128_enc.h"
+#include "aes128_dec.h"
+#include "aes_keyschedule.h"
+#include "keysize_descriptor.h"
+
+const char aes128_str[] PROGMEM = "AES-128";
+
+const uint8_t aes128_keysize_desc[] PROGMEM = { KS_TYPE_LIST, 1, KS_INT(128),
+ KS_TYPE_TERMINATOR };
+
+const bcdesc_t aes128_desc PROGMEM = {
+ BCDESC_TYPE_BLOCKCIPHER,
+ BC_INIT_TYPE_1,
+ aes128_str,
+ sizeof(aes128_ctx_t),
+ 128,
+ {(void_fpt)aes128_init},
+ {(void_fpt)aes128_enc},
+ {(void_fpt)aes128_dec},
+ (bc_free_fpt)NULL,
+ aes128_keysize_desc
+};
+
+
--- /dev/null
+/* bcal_aes128.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file bcal_aes128.c
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-08
+ * \license GPLv3 or later
+ *
+ */
+
+#include <avr/pgmspace.h>
+#include <stdlib.h>
+#include "blockcipher_descriptor.h"
+#include "aes.h"
+#include "aes128_enc.h"
+#include "aes128_dec.h"
+#include "aes_keyschedule.h"
+#include "keysize_descriptor.h"
+
+const char aes128_str[] PROGMEM = "AES-128";
+
+const uint8_t aes128_keysize_desc[] PROGMEM = { KS_TYPE_LIST, 1, KS_INT(128),
+ KS_TYPE_TERMINATOR };
+
+const bcdesc_t aes128_desc PROGMEM = {
+ BCDESC_TYPE_BLOCKCIPHER,
+ BC_INIT_TYPE_1,
+ aes128_str,
+ sizeof(aes128_ctx_t),
+ 128,
+ {(void_fpt)aes128_init},
+ {(void_fpt)aes128_enc},
+ {(void_fpt)aes128_dec},
+ (bc_free_fpt)NULL,
+ aes128_keysize_desc
+};
+
+
--- /dev/null
+/* bcal_aes128.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file bcal_aes128.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-08
+ * \license GPLv3 or later
+ *
+ */
+#if (defined(__AVR__))
+#include <avr\pgmspace.h>
+#else
+#include <pgmspace.h>
+#endif
+#include "blockcipher_descriptor.h"
+#include "aes.h"
+#include "aes128_enc.h"
+#include "aes128_dec.h"
+#include "keysize_descriptor.h"
+
+extern const bcdesc_t aes128_desc;
--- /dev/null
+/* bcal_aes128.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file bcal_aes128.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-08
+ * \license GPLv3 or later
+ *
+ */
+
+#include <avr/pgmspace.h>
+#include "blockcipher_descriptor.h"
+#include "aes.h"
+#include "aes128_enc.h"
+#include "aes128_dec.h"
+#include "keysize_descriptor.h"
+
+extern const bcdesc_t aes128_desc;
--- /dev/null
+/* bcal_aes192.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file bcal_aes192.c
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-08
+ * \license GPLv3 or later
+ *
+ */
+#if (defined(__AVR__))
+#include <avr\pgmspace.h>
+#else
+#include <pgmspace.h>
+#endif
+
+#include <stdlib.h>
+#include "blockcipher_descriptor.h"
+#include "aes.h"
+#include "aes192_enc.h"
+#include "aes192_dec.h"
+#include "aes_keyschedule.h"
+#include "keysize_descriptor.h"
+
+const char aes192_str[] PROGMEM = "AES-192";
+
+const uint8_t aes192_keysize_desc[] PROGMEM = { KS_TYPE_LIST, 1, KS_INT(192),
+ KS_TYPE_TERMINATOR };
+
+const bcdesc_t aes192_desc PROGMEM = {
+ BCDESC_TYPE_BLOCKCIPHER,
+ BC_INIT_TYPE_1,
+ aes192_str,
+ sizeof(aes192_ctx_t),
+ 128,
+ {(void_fpt)aes192_init},
+ {(void_fpt)aes192_enc},
+ {(void_fpt)aes192_dec},
+ (bc_free_fpt)NULL,
+ aes192_keysize_desc
+};
+
+
--- /dev/null
+/* bcal_aes192.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file bcal_aes192.c
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-08
+ * \license GPLv3 or later
+ *
+ */
+
+#include <avr/pgmspace.h>
+#include <stdlib.h>
+#include "blockcipher_descriptor.h"
+#include "aes.h"
+#include "aes192_enc.h"
+#include "aes192_dec.h"
+#include "aes_keyschedule.h"
+#include "keysize_descriptor.h"
+
+const char aes192_str[] PROGMEM = "AES-192";
+
+const uint8_t aes192_keysize_desc[] PROGMEM = { KS_TYPE_LIST, 1, KS_INT(192),
+ KS_TYPE_TERMINATOR };
+
+const bcdesc_t aes192_desc PROGMEM = {
+ BCDESC_TYPE_BLOCKCIPHER,
+ BC_INIT_TYPE_1,
+ aes192_str,
+ sizeof(aes192_ctx_t),
+ 128,
+ {(void_fpt)aes192_init},
+ {(void_fpt)aes192_enc},
+ {(void_fpt)aes192_dec},
+ (bc_free_fpt)NULL,
+ aes192_keysize_desc
+};
+
+
--- /dev/null
+/* bcal_aes192.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file bcal_aes192.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-08
+ * \license GPLv3 or later
+ *
+ */
+
+#if (defined(__AVR__))
+#include <avr\pgmspace.h>
+#else
+#include <pgmspace.h>
+#endif
+#include "blockcipher_descriptor.h"
+#include "aes.h"
+#include "aes192_enc.h"
+#include "aes192_dec.h"
+#include "keysize_descriptor.h"
+
+extern const bcdesc_t aes192_desc;
--- /dev/null
+/* bcal_aes192.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file bcal_aes192.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-08
+ * \license GPLv3 or later
+ *
+ */
+
+#include <avr/pgmspace.h>
+#include "blockcipher_descriptor.h"
+#include "aes.h"
+#include "aes192_enc.h"
+#include "aes192_dec.h"
+#include "keysize_descriptor.h"
+
+extern const bcdesc_t aes192_desc;
--- /dev/null
+/* bcal_aes256.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file bcal_aes256.c
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-08
+ * \license GPLv3 or later
+ *
+ */
+
+#if (defined(__AVR__))
+#include <avr\pgmspace.h>
+#else
+#include <pgmspace.h>
+#endif
+#include <stdlib.h>
+#include "blockcipher_descriptor.h"
+#include "aes.h"
+#include "aes256_enc.h"
+#include "aes256_dec.h"
+#include "aes_keyschedule.h"
+#include "keysize_descriptor.h"
+
+const char aes256_str[] PROGMEM = "AES-256";
+
+const uint8_t aes256_keysize_desc[] PROGMEM = { KS_TYPE_LIST, 1, KS_INT(256),
+ KS_TYPE_TERMINATOR };
+
+const bcdesc_t aes256_desc PROGMEM = {
+ BCDESC_TYPE_BLOCKCIPHER,
+ BC_INIT_TYPE_1,
+ aes256_str,
+ sizeof(aes256_ctx_t),
+ 128,
+ {(void_fpt)aes256_init},
+ {(void_fpt)aes256_enc},
+ {(void_fpt)aes256_dec},
+ (bc_free_fpt)NULL,
+ aes256_keysize_desc
+};
+
+
--- /dev/null
+/* bcal_aes256.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file bcal_aes256.c
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-08
+ * \license GPLv3 or later
+ *
+ */
+
+#include <avr/pgmspace.h>
+#include <stdlib.h>
+#include "blockcipher_descriptor.h"
+#include "aes.h"
+#include "aes256_enc.h"
+#include "aes256_dec.h"
+#include "aes_keyschedule.h"
+#include "keysize_descriptor.h"
+
+const char aes256_str[] PROGMEM = "AES-256";
+
+const uint8_t aes256_keysize_desc[] PROGMEM = { KS_TYPE_LIST, 1, KS_INT(256),
+ KS_TYPE_TERMINATOR };
+
+const bcdesc_t aes256_desc PROGMEM = {
+ BCDESC_TYPE_BLOCKCIPHER,
+ BC_INIT_TYPE_1,
+ aes256_str,
+ sizeof(aes256_ctx_t),
+ 128,
+ {(void_fpt)aes256_init},
+ {(void_fpt)aes256_enc},
+ {(void_fpt)aes256_dec},
+ (bc_free_fpt)NULL,
+ aes256_keysize_desc
+};
+
+
--- /dev/null
+/* bcal_aes256.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file bcal_aes256.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-08
+ * \license GPLv3 or later
+ *
+ */
+
+#if (defined(__AVR__))
+#include <avr\pgmspace.h>
+#else
+#include <pgmspace.h>
+#endif
+#include "blockcipher_descriptor.h"
+#include "aes.h"
+#include "aes256_enc.h"
+#include "aes256_dec.h"
+#include "keysize_descriptor.h"
+
+extern const bcdesc_t aes256_desc;
--- /dev/null
+/* bcal_aes256.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file bcal_aes256.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-08
+ * \license GPLv3 or later
+ *
+ */
+
+#include <avr/pgmspace.h>
+#include "blockcipher_descriptor.h"
+#include "aes.h"
+#include "aes256_enc.h"
+#include "aes256_dec.h"
+#include "keysize_descriptor.h"
+
+extern const bcdesc_t aes256_desc;
--- /dev/null
+/* blockcipher_descriptor.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file blockcipher_descriptor.h
+ * \author Daniel Otte
+ * \date 2009-02-04
+ *
+ * \license GPLv3 or later
+ *
+ */
+
+#ifndef BLOCKCIPHER_DESCRIPTOR_H_
+#define BLOCKCIPHER_DESCRIPTOR_H_
+#include <stdint.h>
+#if (defined(__AVR__))
+#include <avr\pgmspace.h>
+#else
+#include <pgmspace.h>
+#endif
+
+
+#ifndef VOID_FPT
+#define VOID_FPT
+typedef void(*void_fpt)(void);
+#endif
+
+typedef void(*bc_init1_fpt)(void*, void*);
+typedef void(*bc_init2_fpt)(void*, uint16_t,void*);
+typedef void(*bc_enc1_fpt)(void*, void*);
+typedef void(*bc_enc2_fpt)(void*, void*, void*);
+typedef void(*bc_dec1_fpt)(void*, void*);
+typedef void(*bc_dec2_fpt)(void*, void*, void*);
+typedef void(*bc_free_fpt)(void*);
+
+typedef union{
+ void_fpt initvoid;
+ bc_init1_fpt init1;
+ bc_init2_fpt init2;
+} bc_init_fpt;
+
+typedef union{
+ void_fpt encvoid;
+ bc_enc1_fpt enc1;
+ bc_enc2_fpt enc2;
+} bc_enc_fpt;
+
+typedef union{
+ void_fpt decvoid;
+ bc_dec1_fpt dec1;
+ bc_dec2_fpt dec2;
+} bc_dec_fpt;
+
+#define BC_INIT_TYPE 0x01
+#define BC_INIT_TYPE_1 0x00 /* for fix keylength */
+#define BC_INIT_TYPE_2 0x01 /* keylength is passed as second parameter */
+
+#define BC_ENC_TYPE 0x02
+#define BC_ENC_TYPE_1 0x00
+#define BC_ENC_TYPE_2 0x02
+#
+#define BC_DEC_TYPE 0x04
+#define BC_DEC_TYPE_1 0x00
+#define BC_DEC_TYPE_2 0x04
+
+#define BCDESC_TYPE_BLOCKCIPHER 0x01
+
+typedef struct {
+ uint8_t type; /* 1==blockcipher */
+ uint8_t flags;
+ PGM_P name;
+ uint16_t ctxsize_B;
+ uint16_t blocksize_b;
+ bc_init_fpt init;
+ bc_enc_fpt enc;
+ bc_dec_fpt dec;
+ bc_free_fpt free;
+ PGM_VOID_P valid_keysize_desc;
+} bcdesc_t; /* blockcipher descriptor type */
+
+typedef struct{
+ bcdesc_t* desc_ptr;
+ uint16_t keysize;
+ void* ctx;
+} bcgen_ctx_t;
+
+#endif /* BLOCKCIPHER_DESCRIPTOR_H_ */
+
--- /dev/null
+/* blockcipher_descriptor.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file blockcipher_descriptor.h
+ * \author Daniel Otte
+ * \date 2009-02-04
+ *
+ * \license GPLv3 or later
+ *
+ */
+
+#ifndef BLOCKCIPHER_DESCRIPTOR_H_
+#define BLOCKCIPHER_DESCRIPTOR_H_
+#include <stdint.h>
+#include <avr/pgmspace.h>
+
+
+#ifndef VOID_FPT
+#define VOID_FPT
+typedef void(*void_fpt)(void);
+#endif
+
+typedef void(*bc_init1_fpt)(void*, void*);
+typedef void(*bc_init2_fpt)(void*, uint16_t,void*);
+typedef void(*bc_enc1_fpt)(void*, void*);
+typedef void(*bc_enc2_fpt)(void*, void*, void*);
+typedef void(*bc_dec1_fpt)(void*, void*);
+typedef void(*bc_dec2_fpt)(void*, void*, void*);
+typedef void(*bc_free_fpt)(void*);
+
+typedef union{
+ void_fpt initvoid;
+ bc_init1_fpt init1;
+ bc_init2_fpt init2;
+} bc_init_fpt;
+
+typedef union{
+ void_fpt encvoid;
+ bc_enc1_fpt enc1;
+ bc_enc2_fpt enc2;
+} bc_enc_fpt;
+
+typedef union{
+ void_fpt decvoid;
+ bc_dec1_fpt dec1;
+ bc_dec2_fpt dec2;
+} bc_dec_fpt;
+
+#define BC_INIT_TYPE 0x01
+#define BC_INIT_TYPE_1 0x00 /* for fix keylength */
+#define BC_INIT_TYPE_2 0x01 /* keylength is passed as second parameter */
+
+#define BC_ENC_TYPE 0x02
+#define BC_ENC_TYPE_1 0x00
+#define BC_ENC_TYPE_2 0x02
+#
+#define BC_DEC_TYPE 0x04
+#define BC_DEC_TYPE_1 0x00
+#define BC_DEC_TYPE_2 0x04
+
+#define BCDESC_TYPE_BLOCKCIPHER 0x01
+
+typedef struct {
+ uint8_t type; /* 1==blockcipher */
+ uint8_t flags;
+ PGM_P name;
+ uint16_t ctxsize_B;
+ uint16_t blocksize_b;
+ bc_init_fpt init;
+ bc_enc_fpt enc;
+ bc_dec_fpt dec;
+ bc_free_fpt free;
+ PGM_VOID_P valid_keysize_desc;
+} bcdesc_t; /* blockcipher descriptor type */
+
+typedef struct{
+ bcdesc_t* desc_ptr;
+ uint16_t keysize;
+ void* ctx;
+} bcgen_ctx_t;
+
+#endif /* BLOCKCIPHER_DESCRIPTOR_H_ */
+
--- /dev/null
+/* gf256mul.S */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * File: gf256mul.S
+ * Author: Daniel Otte
+ * Date: 2008-12-19
+ * License: GPLv3 or later
+ * Description: peasant's algorithm for multiplication in GF(2^8)
+ *
+ */
+
+//#include <avr/io.h>
+#define OPTIMIZE_SMALL_A
+
+/*
+ * param a: r24
+ * param b: r22
+ * param reducer: r20
+ */
+A = 23
+B = 22
+P = 24
+.global gf256mul
+
+#ifdef OPTIMIZE_SMALL_A
+gf256mul:
+ mov A, r24
+ clr r24
+1:
+ lsr A
+ breq 4f
+ brcc 2f
+ eor P, B
+2:
+ lsl B
+ brcc 3f
+ eor B, r20
+3:
+ rjmp 1b
+4:
+ brcc 2f
+ eor P, B
+2:
+ ret
+
+#else
+
+gf256mul:
+ mov r21, r24
+ clr r24
+ ldi r25, 8
+1:
+ lsr A
+ brcc 2f
+ eor P, B
+2:
+ lsl B
+ brcc 3f
+ eor B, r20
+3:
+ dec r25
+ brne 1b
+ ret
+
+#endif
--- /dev/null
+/* gf256mul.S */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * File: gf256mul.S
+ * Author: Daniel Otte
+ * Date: 2008-12-19
+ * License: GPLv3 or later
+ * Description: peasant's algorithm for multiplication in GF(2^8)
+ *
+ */
+
+#include <avr/io.h>
+#define OPTIMIZE_SMALL_A
+
+/*
+ * param a: r24
+ * param b: r22
+ * param reducer: r20
+ */
+A = 23
+B = 22
+P = 24
+.global gf256mul
+
+#ifdef OPTIMIZE_SMALL_A
+gf256mul:
+ mov A, r24
+ clr r24
+1:
+ lsr A
+ breq 4f
+ brcc 2f
+ eor P, B
+2:
+ lsl B
+ brcc 3f
+ eor B, r20
+3:
+ rjmp 1b
+4:
+ brcc 2f
+ eor P, B
+2:
+ ret
+
+#else
+
+gf256mul:
+ mov r21, r24
+ clr r24
+ ldi r25, 8
+1:
+ lsr A
+ brcc 2f
+ eor P, B
+2:
+ lsl B
+ brcc 3f
+ eor B, r20
+3:
+ dec r25
+ brne 1b
+ ret
+
+#endif
--- /dev/null
+/* gf256mul.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef GF256MUL_H_
+#define GF256MUL_H_
+
+/**
+ * \author Daniel Otte
+ * \email daniel.otte@rub.de
+ * \date 2008-12-19
+ * \license GPLv3
+ * \brief
+ *
+ *
+ */
+
+#include <stdint.h>
+
+uint8_t gf256mul(uint8_t a, uint8_t b, uint8_t reducer);
+
+#endif /* GF256MUL_H_ */
+
--- /dev/null
+/* keysize_descriptor.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file keysize_descriptor.c
+ * \author Daniel Otte
+ * \email daniel.otte@rub.de
+ * \date 2009-01-07
+ * \license GPLv3 or later
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#if (defined(__AVR__))
+#include <avr\pgmspace.h>
+#else
+#include <pgmspace.h>
+#endif
+#include "keysize_descriptor.h"
+
+uint8_t is_valid_keysize_P(PGM_VOID_P ks_desc, uint16_t keysize){
+ uint8_t type;
+ type = pgm_read_byte(ks_desc++);
+ if(type==KS_TYPE_TERMINATOR)
+ return 0;
+ if(type==KS_TYPE_LIST){
+ uint8_t items;
+ uint16_t item;
+ items = pgm_read_byte(ks_desc++);
+ while(items--){
+ item = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ if(item==keysize)
+ return 1;
+ }
+ ks_desc = (uint8_t*)ks_desc - 2;
+ }
+ if(type==KS_TYPE_RANGE){
+ uint16_t max, min;
+ min = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ max = pgm_read_word(ks_desc);
+ if(min<=keysize && keysize<=max)
+ return 1;
+ }
+ if(type==KS_TYPE_ARG_RANGE){
+ uint16_t max, min, dist, offset;
+ min = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ max = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ dist = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ offset = pgm_read_word(ks_desc);
+ if(min<=keysize && keysize<=max && (keysize%dist==offset))
+ return 1;
+ }
+ if(type>KS_TYPE_ARG_RANGE){
+ /* bad error, you may insert a big warning message here */
+ return 0;
+ }
+ return is_valid_keysize_P((uint8_t*)ks_desc+1, keysize); /* search the next record */
+}
+
+uint16_t get_keysize(PGM_VOID_P ks_desc){
+ uint8_t type;
+ uint16_t keysize;
+ type = pgm_read_byte(ks_desc);
+ if(type==KS_TYPE_LIST){
+ ks_desc = (uint8_t*)ks_desc + 1;
+ }
+ ks_desc = (uint8_t*)ks_desc + 1;
+ keysize = pgm_read_word(ks_desc);
+ return keysize;
+}
+
+uint16_t get_keysizes(PGM_VOID_P ks_desc, uint16_t** list){
+ uint8_t type;
+ uint16_t items;
+ uint8_t i;
+ type = pgm_read_byte(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 1;
+ if(type==KS_TYPE_LIST){
+ items = pgm_read_byte(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 1;
+ if(!*list){
+ *list = malloc(items*2);
+ if(!*list){
+ return 0;
+ }
+ }
+ for(i=0; i<items; ++i){
+ ((uint16_t*)(*list))[i] = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ }
+ return items;
+ }
+ if(type==KS_TYPE_ARG_RANGE){
+ uint16_t min, max, distance, offset;
+ min = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ max = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ distance = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ offset = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ items = (max-min)/distance+1;
+ if(min%distance!=offset){
+ --items;
+ min += (distance-(min%distance-offset))%distance;
+ }
+ if(!*list){
+ *list = malloc(items*2);
+ if(!*list){
+ return 0;
+ }
+ }
+ i=0;
+ while(min<max){
+ ((uint16_t*)*list)[i++] = min;
+ min += distance;
+ }
+ return i;
+ }
+ if(type==KS_TYPE_RANGE){
+ uint16_t min, max, distance=8, offset=0;
+ min = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ max = pgm_read_word(ks_desc);
+ items = (max-min)/distance+1;
+ if(min%distance!=offset){
+ --items;
+ min += (distance-(min%distance-offset))%distance;
+ }
+ if(!*list){
+ *list = malloc(items*2);
+ if(!*list){
+ return 0;
+ }
+ }
+ i=0;
+ while(min<max){
+ ((uint16_t*)*list)[i++] = min;
+ min += distance;
+ }
+ return i;
+ }
+ return 0;
+}
--- /dev/null
+/* keysize_descriptor.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file keysize_descriptor.c
+ * \author Daniel Otte
+ * \email daniel.otte@rub.de
+ * \date 2009-01-07
+ * \license GPLv3 or later
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <avr/pgmspace.h>
+#include "keysize_descriptor.h"
+
+uint8_t is_valid_keysize_P(PGM_VOID_P ks_desc, uint16_t keysize){
+ uint8_t type;
+ type = pgm_read_byte(ks_desc++);
+ if(type==KS_TYPE_TERMINATOR)
+ return 0;
+ if(type==KS_TYPE_LIST){
+ uint8_t items;
+ uint16_t item;
+ items = pgm_read_byte(ks_desc++);
+ while(items--){
+ item = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ if(item==keysize)
+ return 1;
+ }
+ ks_desc = (uint8_t*)ks_desc - 2;
+ }
+ if(type==KS_TYPE_RANGE){
+ uint16_t max, min;
+ min = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ max = pgm_read_word(ks_desc);
+ if(min<=keysize && keysize<=max)
+ return 1;
+ }
+ if(type==KS_TYPE_ARG_RANGE){
+ uint16_t max, min, dist, offset;
+ min = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ max = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ dist = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ offset = pgm_read_word(ks_desc);
+ if(min<=keysize && keysize<=max && (keysize%dist==offset))
+ return 1;
+ }
+ if(type>KS_TYPE_ARG_RANGE){
+ /* bad error, you may insert a big warning message here */
+ return 0;
+ }
+ return is_valid_keysize_P((uint8_t*)ks_desc+1, keysize); /* search the next record */
+}
+
+uint16_t get_keysize(PGM_VOID_P ks_desc){
+ uint8_t type;
+ uint16_t keysize;
+ type = pgm_read_byte(ks_desc);
+ if(type==KS_TYPE_LIST){
+ ks_desc = (uint8_t*)ks_desc + 1;
+ }
+ ks_desc = (uint8_t*)ks_desc + 1;
+ keysize = pgm_read_word(ks_desc);
+ return keysize;
+}
+
+uint16_t get_keysizes(PGM_VOID_P ks_desc, uint16_t** list){
+ uint8_t type;
+ uint16_t items;
+ uint8_t i;
+ type = pgm_read_byte(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 1;
+ if(type==KS_TYPE_LIST){
+ items = pgm_read_byte(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 1;
+ if(!*list){
+ *list = malloc(items*2);
+ if(!*list){
+ return 0;
+ }
+ }
+ for(i=0; i<items; ++i){
+ ((uint16_t*)(*list))[i] = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ }
+ return items;
+ }
+ if(type==KS_TYPE_ARG_RANGE){
+ uint16_t min, max, distance, offset;
+ min = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ max = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ distance = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ offset = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ items = (max-min)/distance+1;
+ if(min%distance!=offset){
+ --items;
+ min += (distance-(min%distance-offset))%distance;
+ }
+ if(!*list){
+ *list = malloc(items*2);
+ if(!*list){
+ return 0;
+ }
+ }
+ i=0;
+ while(min<max){
+ ((uint16_t*)*list)[i++] = min;
+ min += distance;
+ }
+ return i;
+ }
+ if(type==KS_TYPE_RANGE){
+ uint16_t min, max, distance=8, offset=0;
+ min = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ max = pgm_read_word(ks_desc);
+ items = (max-min)/distance+1;
+ if(min%distance!=offset){
+ --items;
+ min += (distance-(min%distance-offset))%distance;
+ }
+ if(!*list){
+ *list = malloc(items*2);
+ if(!*list){
+ return 0;
+ }
+ }
+ i=0;
+ while(min<max){
+ ((uint16_t*)*list)[i++] = min;
+ min += distance;
+ }
+ return i;
+ }
+ return 0;
+}
--- /dev/null
+/* keysize_descriptor.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file keysize_descriptor.h
+ * \author Daniel Otte
+ * \email daniel.otte@rub.de
+ * \date 2009-01-07
+ * \license GPLv3 or later
+ */
+
+#ifndef KEYSIZE_DESCRIPTOR_H_
+#define KEYSIZE_DESCRIPTOR_H_
+
+#include <stdint.h>
+#if (defined(__AVR__))
+#include <avr\pgmspace.h>
+#else
+#include <pgmspace.h>
+#endif
+
+#define KS_TYPE_TERMINATOR 0x00
+#define KS_TYPE_LIST 0x01
+#define KS_TYPE_RANGE 0x02
+#define KS_TYPE_ARG_RANGE 0x03
+
+#define KS_INT(a) ((a)&0xFF), ((a)>>8)
+
+typedef struct{ /* keysize is valid if listed in items */
+ uint8_t n_items; /* number of items (value 0 is reserved) */
+ uint16_t items[]; /* list of valid lengths */
+}keysize_desc_list_t;
+
+typedef struct{ /* keysize is valid if min<=keysize<=max */
+ uint16_t min;
+ uint16_t max;
+}keysize_desc_range_t;
+
+typedef struct{ /* keysize is valid if min<=keysize<=max and if keysize mod distance == offset */
+ uint16_t min;
+ uint16_t max;
+ uint16_t distance;
+ uint16_t offset;
+}keysize_desc_arg_range_t;
+
+uint8_t is_valid_keysize_P(PGM_VOID_P ks_desc, uint16_t keysize);
+uint16_t get_keysize(PGM_VOID_P ks_desc);
+uint16_t get_keysizes(PGM_VOID_P ks_desc, uint16_t** list);
+
+
+#endif /* KEYSIZE_DESCRIPTOR_H_ */
--- /dev/null
+/* keysize_descriptor.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file keysize_descriptor.h
+ * \author Daniel Otte
+ * \email daniel.otte@rub.de
+ * \date 2009-01-07
+ * \license GPLv3 or later
+ */
+
+#ifndef KEYSIZE_DESCRIPTOR_H_
+#define KEYSIZE_DESCRIPTOR_H_
+
+#include <stdint.h>
+#include <avr/pgmspace.h>
+
+#define KS_TYPE_TERMINATOR 0x00
+#define KS_TYPE_LIST 0x01
+#define KS_TYPE_RANGE 0x02
+#define KS_TYPE_ARG_RANGE 0x03
+
+#define KS_INT(a) ((a)&0xFF), ((a)>>8)
+
+typedef struct{ /* keysize is valid if listed in items */
+ uint8_t n_items; /* number of items (value 0 is reserved) */
+ uint16_t items[]; /* list of valid lengths */
+}keysize_desc_list_t;
+
+typedef struct{ /* keysize is valid if min<=keysize<=max */
+ uint16_t min;
+ uint16_t max;
+}keysize_desc_range_t;
+
+typedef struct{ /* keysize is valid if min<=keysize<=max and if keysize mod distance == offset */
+ uint16_t min;
+ uint16_t max;
+ uint16_t distance;
+ uint16_t offset;
+}keysize_desc_arg_range_t;
+
+uint8_t is_valid_keysize_P(PGM_VOID_P ks_desc, uint16_t keysize);
+uint16_t get_keysize(PGM_VOID_P ks_desc);
+uint16_t get_keysizes(PGM_VOID_P ks_desc, uint16_t** list);
+
+
+#endif /* KEYSIZE_DESCRIPTOR_H_ */
--- /dev/null
+{
+ "name": "AESLib",
+ "keywords": "cryptography, aes",
+ "description": "Small AES implementation in ASM",
+ "repository":
+ {
+ "type": "git",
+ "url": "https://github.com/DavyLandman/AESLib.git"
+ },
+ "frameworks": "arduino",
+ "platforms": "atmelavr"
+}
--- /dev/null
+/* memxor.S */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * File: memxor.S
+ * Author: Daniel Otte
+ * Date: 2008-08-07
+ * License: GPLv3 or later
+ * Description: memxor, XORing one block into another
+ *
+ */
+
+/*
+ * void memxor(void* dest, const void* src, uint16_t n);
+ */
+ /*
+ * param dest is passed in r24:r25
+ * param src is passed in r22:r23
+ * param n is passed in r20:r21
+ */
+.global memxor
+memxor:
+ movw r30, r24
+ movw r26, r22
+ movw r24, r20
+ adiw r24, 0
+ breq 2f
+1:
+ ld r20, X+
+ ld r21, Z
+ eor r20, r21
+ st Z+, r20
+ sbiw r24, 1
+ brne 1b
+2:
+ ret
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+#ifndef MEMXOR_H_
+#define MEMXOR_H_
+#include <stdint.h>
+
+void memxor(void* dest, const void* src, uint16_t n);
+void memxor_P(void* dest, const void* src, uint16_t n);
+
+
+#endif
--- /dev/null
+aes/
+gf256mul/
+memxor/
+bcal/
+*.swp
+*.o
+.DS_Store
--- /dev/null
+/*
+ This file is part of the aeslib.
+ Copyright (C) 2012 Davy Landman (davy.landman@gmail.com)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+#include "AESLib.h"
+#include <stdint.h>
+#include "aes.h"
+#include "blockcipher_descriptor.h"
+#include "bcal_aes128.h"
+#include "bcal_aes192.h"
+#include "bcal-cbc.h"
+#if (defined(AVR))
+#include <avr\pgmspace.h>
+#else
+#include <pgmspace.h>
+#endif
+
+// encrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+void aes128_cbc_enc(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t ctx;
+ uint8_t r;
+ r = bcal_cbc_init(&aes128_desc, key, 128, &ctx);
+ if (r) {
+ return;
+ }
+ bcal_cbc_encMsg(iv, data, data_len / 16, &ctx);
+ bcal_cbc_free(&ctx);
+}
+
+// encrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+void aes192_cbc_enc(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t ctx;
+ uint8_t r;
+ r = bcal_cbc_init(&aes192_desc, key, 192, &ctx);
+ if (r) {
+ return;
+ }
+ bcal_cbc_encMsg(iv, data, data_len / 16, &ctx);
+ bcal_cbc_free(&ctx);
+}
+
+// encrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+void aes128_enc_single(const uint8_t* key, void* data){
+ aes128_ctx_t ctx;
+ aes128_init(key, &ctx);
+ aes128_enc(data, &ctx);
+}
+
+// encrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key is assumed to be 256bit thus 32 uint8_t's
+void aes256_enc_single(const uint8_t* key, void* data){
+ aes256_ctx_t ctx;
+ aes256_init(key, &ctx);
+ aes256_enc(data, &ctx);
+}
+
+
+// prepare an encrypted to use for encrypting multiple blocks lateron.
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+aes_context aes128_cbc_enc_start(const uint8_t* key, const void* iv){
+ bcal_cbc_ctx_t* ctx = (bcal_cbc_ctx_t*)malloc(sizeof(bcal_cbc_ctx_t));
+ uint8_t r = bcal_cbc_init(&aes128_desc, key, 128, ctx);
+ if (r) {
+ free(ctx);
+ return NULL;
+ }
+ bcal_cbc_loadIV(iv, ctx);
+ return (aes_context)ctx;
+}
+
+// prepare an encrypted to use for encrypting multiple blocks lateron.
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+aes_context aes192_cbc_enc_start(const uint8_t* key, const void* iv){
+ bcal_cbc_ctx_t* ctx = (bcal_cbc_ctx_t*)malloc(sizeof(bcal_cbc_ctx_t));
+ uint8_t r = bcal_cbc_init(&aes192_desc, key, 192, ctx);
+ if (r) {
+ free(ctx);
+ return NULL;
+ }
+ bcal_cbc_loadIV(iv, ctx);
+ return (aes_context)ctx;
+}
+
+// encrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes128_cbc_enc_continue(const aes_context ctx, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t* _ctx = (bcal_cbc_ctx_t*)ctx;
+ uint16_t msg_blocks = data_len / 16;
+ while(msg_blocks--){
+ bcal_cbc_encNext(data, _ctx);
+ data = (uint8_t*)data + _ctx->blocksize_B;
+ }
+}
+
+// encrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes192_cbc_enc_continue(const aes_context ctx, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t* _ctx = (bcal_cbc_ctx_t*)ctx;
+ uint16_t msg_blocks = data_len / 16;
+ while(msg_blocks--){
+ bcal_cbc_encNext(data, _ctx);
+ data = (uint8_t*)data + _ctx->blocksize_B;
+ }
+}
+
+// cleanup encryption context
+void aes128_cbc_enc_finish(const aes_context ctx){
+ bcal_cbc_free((bcal_cbc_ctx_t*)ctx);
+ free(ctx);
+}
+
+// cleanup encryption context
+void aes192_cbc_enc_finish(const aes_context ctx){
+ bcal_cbc_free((bcal_cbc_ctx_t*)ctx);
+ free(ctx);
+}
+
+// decrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+void aes128_cbc_dec(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t ctx;
+ uint8_t r;
+ r = bcal_cbc_init(&aes128_desc, key, 128, &ctx);
+ if (r) {
+ return;
+ }
+ bcal_cbc_decMsg(iv, data, data_len / 16, &ctx);
+ bcal_cbc_free(&ctx);
+}
+
+// decrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+void aes192_cbc_dec(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t ctx;
+ uint8_t r;
+ r = bcal_cbc_init(&aes192_desc, key, 192, &ctx);
+ if (r) {
+ return;
+ }
+ bcal_cbc_decMsg(iv, data, data_len / 16, &ctx);
+ bcal_cbc_free(&ctx);
+}
+
+// decrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key is assumed to be 128bit thus 16 uint8_t's
+void aes128_dec_single(const uint8_t* key, void* data){
+ aes128_ctx_t ctx;
+ aes128_init(key, &ctx);
+ aes128_dec(data, &ctx);
+}
+
+// decrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key is assumed to be 256bit thus 32 uint8_t's
+void aes256_dec_single(const uint8_t* key, void* data){
+ aes256_ctx_t ctx;
+ aes256_init(key, &ctx);
+ aes256_dec(data, &ctx);
+}
+
+
+// prepare an decrypted to use for decrypting multiple blocks lateron.
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+aes_context aes128_cbc_dec_start(const uint8_t* key, const void* iv){
+ bcal_cbc_ctx_t* ctx = (bcal_cbc_ctx_t*)malloc(sizeof(bcal_cbc_ctx_t));
+ uint8_t r = bcal_cbc_init(&aes128_desc, key, 128, ctx);
+ if (r) {
+ free(ctx);
+ return NULL;
+ }
+ bcal_cbc_loadIV(iv, ctx);
+ return (aes_context)ctx;
+}
+
+// prepare an decrypted to use for decrypting multiple blocks lateron.
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+aes_context aes192_cbc_dec_start(const uint8_t* key, const void* iv){
+ bcal_cbc_ctx_t* ctx = (bcal_cbc_ctx_t*)malloc(sizeof(bcal_cbc_ctx_t));
+ uint8_t r = bcal_cbc_init(&aes192_desc, key, 192, ctx);
+ if (r) {
+ free(ctx);
+ return NULL;
+ }
+ bcal_cbc_loadIV(iv, ctx);
+ return (aes_context)ctx;
+}
+
+// decrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes128_cbc_dec_continue(const aes_context ctx, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t* _ctx = (bcal_cbc_ctx_t*)ctx;
+ uint16_t msg_blocks = data_len / 16;
+ while(msg_blocks--){
+ bcal_cbc_decNext(data, _ctx);
+ data = (uint8_t*)data + _ctx->blocksize_B;
+ }
+}
+
+// decrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes192_cbc_dec_continue(const aes_context ctx, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t* _ctx = (bcal_cbc_ctx_t*)ctx;
+ uint16_t msg_blocks = data_len / 16;
+ while(msg_blocks--){
+ bcal_cbc_decNext(data, _ctx);
+ data = (uint8_t*)data + _ctx->blocksize_B;
+ }
+}
+
+// cleanup decryption context
+void aes128_cbc_dec_finish(const aes_context ctx){
+ bcal_cbc_free((bcal_cbc_ctx_t*)ctx);
+ free(ctx);
+}
+
+// cleanup decryption context
+void aes192_cbc_dec_finish(const aes_context ctx){
+ bcal_cbc_free((bcal_cbc_ctx_t*)ctx);
+ free(ctx);
+}
--- /dev/null
+/*
+ This file is part of the aeslib.
+ Copyright (C) 2012 Davy Landman (davy.landman@gmail.com)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+#include "AESLib.h"
+#include <stdint.h>
+#include "aes.h"
+#include "blockcipher_descriptor.h"
+#include "bcal_aes128.h"
+#include "bcal_aes192.h"
+#include "bcal-cbc.h"
+#include <avr/pgmspace.h>
+
+// encrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+void aes128_cbc_enc(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t ctx;
+ uint8_t r;
+ r = bcal_cbc_init(&aes128_desc, key, 128, &ctx);
+ if (r) {
+ return;
+ }
+ bcal_cbc_encMsg(iv, data, data_len / 16, &ctx);
+ bcal_cbc_free(&ctx);
+}
+
+// encrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+void aes192_cbc_enc(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t ctx;
+ uint8_t r;
+ r = bcal_cbc_init(&aes192_desc, key, 192, &ctx);
+ if (r) {
+ return;
+ }
+ bcal_cbc_encMsg(iv, data, data_len / 16, &ctx);
+ bcal_cbc_free(&ctx);
+}
+
+// encrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+void aes128_enc_single(const uint8_t* key, void* data){
+ aes128_ctx_t ctx;
+ aes128_init(key, &ctx);
+ aes128_enc(data, &ctx);
+}
+
+// encrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key is assumed to be 256bit thus 32 uint8_t's
+void aes256_enc_single(const uint8_t* key, void* data){
+ aes256_ctx_t ctx;
+ aes256_init(key, &ctx);
+ aes256_enc(data, &ctx);
+}
+
+
+// prepare an encrypted to use for encrypting multiple blocks lateron.
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+aes_context aes128_cbc_enc_start(const uint8_t* key, const void* iv){
+ bcal_cbc_ctx_t* ctx = (bcal_cbc_ctx_t*)malloc(sizeof(bcal_cbc_ctx_t));
+ uint8_t r = bcal_cbc_init(&aes128_desc, key, 128, ctx);
+ if (r) {
+ free(ctx);
+ return NULL;
+ }
+ bcal_cbc_loadIV(iv, ctx);
+ return (aes_context)ctx;
+}
+
+// prepare an encrypted to use for encrypting multiple blocks lateron.
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+aes_context aes192_cbc_enc_start(const uint8_t* key, const void* iv){
+ bcal_cbc_ctx_t* ctx = (bcal_cbc_ctx_t*)malloc(sizeof(bcal_cbc_ctx_t));
+ uint8_t r = bcal_cbc_init(&aes192_desc, key, 192, ctx);
+ if (r) {
+ free(ctx);
+ return NULL;
+ }
+ bcal_cbc_loadIV(iv, ctx);
+ return (aes_context)ctx;
+}
+
+// encrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes128_cbc_enc_continue(const aes_context ctx, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t* _ctx = (bcal_cbc_ctx_t*)ctx;
+ uint16_t msg_blocks = data_len / 16;
+ while(msg_blocks--){
+ bcal_cbc_encNext(data, _ctx);
+ data = (uint8_t*)data + _ctx->blocksize_B;
+ }
+}
+
+// encrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes192_cbc_enc_continue(const aes_context ctx, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t* _ctx = (bcal_cbc_ctx_t*)ctx;
+ uint16_t msg_blocks = data_len / 16;
+ while(msg_blocks--){
+ bcal_cbc_encNext(data, _ctx);
+ data = (uint8_t*)data + _ctx->blocksize_B;
+ }
+}
+
+// cleanup encryption context
+void aes128_cbc_enc_finish(const aes_context ctx){
+ bcal_cbc_free((bcal_cbc_ctx_t*)ctx);
+ free(ctx);
+}
+
+// cleanup encryption context
+void aes192_cbc_enc_finish(const aes_context ctx){
+ bcal_cbc_free((bcal_cbc_ctx_t*)ctx);
+ free(ctx);
+}
+
+// decrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+void aes128_cbc_dec(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t ctx;
+ uint8_t r;
+ r = bcal_cbc_init(&aes128_desc, key, 128, &ctx);
+ if (r) {
+ return;
+ }
+ bcal_cbc_decMsg(iv, data, data_len / 16, &ctx);
+ bcal_cbc_free(&ctx);
+}
+
+// decrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+void aes192_cbc_dec(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t ctx;
+ uint8_t r;
+ r = bcal_cbc_init(&aes192_desc, key, 192, &ctx);
+ if (r) {
+ return;
+ }
+ bcal_cbc_decMsg(iv, data, data_len / 16, &ctx);
+ bcal_cbc_free(&ctx);
+}
+
+// decrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key is assumed to be 128bit thus 16 uint8_t's
+void aes128_dec_single(const uint8_t* key, void* data){
+ aes128_ctx_t ctx;
+ aes128_init(key, &ctx);
+ aes128_dec(data, &ctx);
+}
+
+// decrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key is assumed to be 256bit thus 32 uint8_t's
+void aes256_dec_single(const uint8_t* key, void* data){
+ aes256_ctx_t ctx;
+ aes256_init(key, &ctx);
+ aes256_dec(data, &ctx);
+}
+
+
+// prepare an decrypted to use for decrypting multiple blocks lateron.
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+aes_context aes128_cbc_dec_start(const uint8_t* key, const void* iv){
+ bcal_cbc_ctx_t* ctx = (bcal_cbc_ctx_t*)malloc(sizeof(bcal_cbc_ctx_t));
+ uint8_t r = bcal_cbc_init(&aes128_desc, key, 128, ctx);
+ if (r) {
+ free(ctx);
+ return NULL;
+ }
+ bcal_cbc_loadIV(iv, ctx);
+ return (aes_context)ctx;
+}
+
+// prepare an decrypted to use for decrypting multiple blocks lateron.
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+aes_context aes192_cbc_dec_start(const uint8_t* key, const void* iv){
+ bcal_cbc_ctx_t* ctx = (bcal_cbc_ctx_t*)malloc(sizeof(bcal_cbc_ctx_t));
+ uint8_t r = bcal_cbc_init(&aes192_desc, key, 192, ctx);
+ if (r) {
+ free(ctx);
+ return NULL;
+ }
+ bcal_cbc_loadIV(iv, ctx);
+ return (aes_context)ctx;
+}
+
+// decrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes128_cbc_dec_continue(const aes_context ctx, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t* _ctx = (bcal_cbc_ctx_t*)ctx;
+ uint16_t msg_blocks = data_len / 16;
+ while(msg_blocks--){
+ bcal_cbc_decNext(data, _ctx);
+ data = (uint8_t*)data + _ctx->blocksize_B;
+ }
+}
+
+// decrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes192_cbc_dec_continue(const aes_context ctx, void* data, const uint16_t data_len){
+ if (data_len % 16 != 0) {
+ return;
+ }
+ bcal_cbc_ctx_t* _ctx = (bcal_cbc_ctx_t*)ctx;
+ uint16_t msg_blocks = data_len / 16;
+ while(msg_blocks--){
+ bcal_cbc_decNext(data, _ctx);
+ data = (uint8_t*)data + _ctx->blocksize_B;
+ }
+}
+
+// cleanup decryption context
+void aes128_cbc_dec_finish(const aes_context ctx){
+ bcal_cbc_free((bcal_cbc_ctx_t*)ctx);
+ free(ctx);
+}
+
+// cleanup decryption context
+void aes192_cbc_dec_finish(const aes_context ctx){
+ bcal_cbc_free((bcal_cbc_ctx_t*)ctx);
+ free(ctx);
+}
--- /dev/null
+/*
+ This file is part of the aeslib.
+ Copyright (C) 2012 Davy Landman (davy.landman@gmail.com)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef AESLIB_H
+#define AESLIB_H
+#include <stdint.h>
+#ifdef __cplusplus
+extern "C"{
+#endif
+// encrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+void aes128_cbc_enc(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len);
+
+// encrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+void aes192_cbc_enc(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len);
+
+// encrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key is assumed to be 128bit thus 16 uint8_t's
+void aes128_enc_single(const uint8_t* key, void* data);
+
+// encrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key is assumed to be 256bit thus 32 uint8_t's
+void aes256_enc_single(const uint8_t* key, void* data);
+
+typedef void* aes_context;
+
+// prepare an encrypted to use for encrypting multiple blocks lateron.
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+aes_context aes128_cbc_enc_start(const uint8_t* key, const void* iv);
+
+// prepare an encrypted to use for encrypting multiple blocks lateron.
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+aes_context aes192_cbc_enc_start(const uint8_t* key, const void* iv);
+
+// encrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes128_cbc_enc_continue(const aes_context ctx, void* data, const uint16_t data_len);
+
+// encrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes192_cbc_enc_continue(const aes_context ctx, void* data, const uint16_t data_len);
+
+// cleanup encryption context
+void aes128_cbc_enc_finish(const aes_context ctx);
+
+// cleanup encryption context
+void aes192_cbc_enc_finish(const aes_context ctx);
+
+// decrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+void aes128_cbc_dec(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len);
+
+// decrypt multiple blocks of 128bit data, data_len but be mod 16
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+void aes192_cbc_dec(const uint8_t* key, const uint8_t* iv, void* data, const uint16_t data_len);
+
+// decrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key is assumed to be 128bit thus 16 uint8_t's
+void aes128_dec_single(const uint8_t* key, void* data);
+
+// decrypt single 128bit block. data is assumed to be 16 uint8_t's
+// key is assumed to be 256bit thus 32 uint8_t's
+void aes256_dec_single(const uint8_t* key, void* data);
+
+// prepare an decrypter to use for decrypting multiple blocks lateron.
+// key and iv are assumed to be both 128bit thus 16 uint8_t's
+aes_context aes128_cbc_dec_start(const uint8_t* key, const void* iv);
+
+// prepare an decrypter to use for decrypting multiple blocks lateron.
+// key and iv are assumed to be both 192bit thus 24 uint8_t's
+aes_context aes192_cbc_dec_start(const uint8_t* key, const void* iv);
+
+// decrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes128_cbc_dec_continue(const aes_context ctx, void* data, const uint16_t data_len);
+
+// decrypt one or more blocks of 128bit data
+// data_len should be mod 16
+void aes192_cbc_dec_continue(const aes_context ctx, void* data, const uint16_t data_len);
+
+// cleanup decryption context
+void aes128_cbc_dec_finish(const aes_context ctx);
+
+// cleanup decryption context
+void aes192_cbc_dec_finish(const aes_context ctx);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
--- /dev/null
+Arduino AESLib
+==============
+
+This project is just an Arduino ready extract from the [AVR-Crypto-Lib](https://github.com/cantora/avr-crypto-lib).
+
+It only packages the ASM implementations of AES into a library ready to use in
+Arduino IDE.
+
+See the LICENSE file for details of the GPLv3 license in which the AVR-Crypo-Lib
+is licensed.
+
+
+Installation
+------------
+
+- Download the files in this repository (using either clone or the download button)
+- Copy the `AESLib` folder into `libraries` folder (same level as your `sketch` folder)
+- add `#include <AESLib.h>` in your sketch.
+
+
+Usage
+-----
+
+At the moment only 128bit keys are supported, the blocksize is also fixed at 128bit.
+This means that the key array and possible iv array should contain exactly 16 bytes (`uint8_t` or `byte`).
+Moreover the amount of bytes to encrypt should be mod 16.
+(this means you have to take care of padding yourself).
+
+The library supports 3 kinds of operations.
+
+1. single block encryption/decryption
+- multiple block encryption/decryption using CBC (single call)
+- multiple block encryption/decryption using CBC (multiple calls)
+
+The single block enc/decryption are the following methods:
+
+```c
+void aes128_enc_single(const uint8_t* key, void* data);
+void aes128_dec_single(const uint8_t* key, void* data);
+```
+
+Usage example:
+
+```c
+Serial.begin(57600);
+uint8_t key[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+char data[] = "0123456789012345"; //16 chars == 16 bytes
+aes128_enc_single(key, data);
+Serial.print("encrypted:");
+Serial.println(data);
+aes128_dec_single(key, data);
+Serial.print("decrypted:");
+Serial.println(data);
+```
+
+Usage example for AES256:
+
+```c
+Serial.begin(57600);
+uint8_t key[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31};
+char data[] = "0123456789012345";
+aes256_enc_single(key, data);
+Serial.print("encrypted:");
+Serial.println(data);
+aes256_dec_single(key, data);
+Serial.print("decrypted:");
+Serial.println(data);
+```
+
+
+
--- /dev/null
+/* aes.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-30
+ * \license GPLv3 or later
+ *
+ */
+#ifndef AES_H_
+#define AES_H_
+
+#include <stdint.h>
+
+#include "aes_types.h"
+#include "aes128_enc.h"
+#include "aes192_enc.h"
+#include "aes256_enc.h"
+#include "aes128_dec.h"
+#include "aes192_dec.h"
+#include "aes256_dec.h"
+#include "aes_enc.h"
+#include "aes_dec.h"
+#include "aes_keyschedule.h"
+
+#endif
--- /dev/null
+/* aes128_dec.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes128_dec.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-30
+ * \license GPLv3 or later
+ * \ingroup AES
+ */
+
+#ifndef AES128_DEC_H_
+#define AES128_DEC_H_
+
+#include "aes_types.h"
+#include "aes_dec.h"
+
+/**
+ * \brief decrypt with 128 bit key.
+ *
+ * This function decrypts one block with the AES algorithm under control of
+ * a keyschedule produced from a 128 bit key.
+ * \param buffer pointer to the block to decrypt
+ * \param ctx pointer to the key schedule
+ */
+void aes128_dec(void* buffer, aes128_ctx_t* ctx);
+
+
+
+#endif /* AES128_DEC_H_ */
--- /dev/null
+/* aes128_enc.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes128_enc.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-30
+ * \license GPLv3 or later
+ * \ingroup AES
+ */
+
+#ifndef AES128_ENC_H_
+#define AES128_ENC_H_
+
+#include "aes_types.h"
+#include "aes_enc.h"
+
+
+/**
+ * \brief encrypt with 128 bit key.
+ *
+ * This function encrypts one block with the AES algorithm under control of
+ * a keyschedule produced from a 128 bit key.
+ * \param buffer pointer to the block to encrypt
+ * \param ctx pointer to the key schedule
+ */
+void aes128_enc(void* buffer, aes128_ctx_t* ctx);
+
+
+
+#endif /* AES128_ENC_H_ */
--- /dev/null
+/* aes192_dec.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes192_dec.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-31
+ * \license GPLv3 or later
+ * \ingroup AES
+ */
+
+#ifndef AES192_DEC_H_
+#define AES192_DEC_H_
+
+#include "aes_types.h"
+#include "aes_dec.h"
+
+/**
+ * \brief decrypt with 192 bit key.
+ *
+ * This function decrypts one block with the AES algorithm under control of
+ * a keyschedule produced from a 192 bit key.
+ * \param buffer pointer to the block to decrypt
+ * \param ctx pointer to the key schedule
+ */
+void aes192_dec(void* buffer, aes192_ctx_t* ctx);
+
+
+
+#endif /* AES192_DEC_H_ */
--- /dev/null
+/* aes192_enc.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes192_enc.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-31
+ * \license GPLv3 or later
+ * \ingroup AES
+ */
+
+#ifndef AES192_ENC_H_
+#define AES192_ENC_H_
+
+#include "aes_types.h"
+#include "aes_enc.h"
+
+
+/**
+ * \brief encrypt with 192 bit key.
+ *
+ * This function encrypts one block with the AES algorithm under control of
+ * a keyschedule produced from a 192 bit key.
+ * \param buffer pointer to the block to encrypt
+ * \param ctx pointer to the key schedule
+ */
+void aes192_enc(void* buffer, aes192_ctx_t* ctx);
+
+
+
+#endif /* AES192_ENC_H_ */
--- /dev/null
+/* aes256_dec.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes256_dec.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-31
+ * \license GPLv3 or later
+ * \ingroup AES
+ */
+
+#ifndef AES256_DEC_H_
+#define AES256_DEC_H_
+
+#include "aes_types.h"
+#include "aes_dec.h"
+
+/**
+ * \brief decrypt with 256 bit key.
+ *
+ * This function decrypts one block with the AES algorithm under control of
+ * a keyschedule produced from a 256 bit key.
+ * \param buffer pointer to the block to decrypt
+ * \param ctx pointer to the key schedule
+ */
+void aes256_dec(void* buffer, aes256_ctx_t* ctx);
+
+
+
+#endif /* AES256_DEC_H_ */
--- /dev/null
+/* aes256_enc.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes256_enc.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-31
+ * \license GPLv3 or later
+ * \ingroup AES
+ */
+
+#ifndef AES256_ENC_H_
+#define AES256_ENC_H_
+
+#include "aes_types.h"
+#include "aes_enc.h"
+
+
+/**
+ * \brief encrypt with 256 bit key.
+ *
+ * This function encrypts one block with the AES algorithm under control of
+ * a keyschedule produced from a 256 bit key.
+ * \param buffer pointer to the block to encrypt
+ * \param ctx pointer to the key schedule
+ */
+void aes256_enc(void* buffer, aes256_ctx_t* ctx);
+
+
+
+#endif /* AES256_ENC_H_ */
--- /dev/null
+/* aes_dec-asm.S */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008, 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes_dec-asm.S
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-10
+ * \license GPLv3 or later
+ *
+ */
+
+#include "avr-asm-macros.S"
+A = 28
+B = 29
+P = 0
+xREDUCER = 25
+
+.global aes256_dec
+aes256_dec:
+ ldi r20, 14
+ rjmp aes_decrypt_core
+
+.global aes192_dec
+aes192_dec:
+ ldi r20, 12
+ rjmp aes_decrypt_core
+
+.global aes128_dec
+aes128_dec:
+ ldi r20, 10
+
+
+/*
+ void aes_decrypt_core(aes_cipher_state_t* state, const aes_genctx_t* ks, uint8_t rounds)
+*/
+T0= 2
+T1= 3
+T2= 4
+T3= 5
+T4 = 6
+T5 = 7
+ST00 = 8
+ST01 = 9
+ST02 = 10
+ST03 = 11
+ST10 = 12
+ST11 = 13
+ST12 = 14
+ST13 = 15
+ST20 = 16
+ST21 = 17
+ST22 = 18
+ST23 = 19
+ST30 = 20
+ST31 = 21
+ST32 = 22
+ST33 = 23
+CTR = 24
+/*
+ * param state: r24:r25
+ * param ks: r22:r23
+ * param rounds: r20
+ */
+.global aes_decrypt_core
+aes_decrypt_core:
+ push_range 2, 17
+ push r28
+ push r29
+ push r24
+ push r25
+ movw r26, r22
+ movw r30, r24
+ mov CTR, r20
+ inc r20
+ swap r20 /* r20*16 */
+ add r26, r20
+ adc r27, r1
+ clt
+ .irp param, ST00, ST01, ST02, ST03, ST10, ST11, ST12, ST13, ST20, ST21, ST22, ST23, ST30, ST31, ST32, ST33
+ ld \param, Z+
+ .endr
+
+ ldi xREDUCER, 0x1b /* load reducer */
+
+
+ .irp param, ST33, ST32, ST31, ST30, ST23, ST22, ST21, ST20, ST13, ST12, ST11, ST10, ST03, ST02, ST01, ST00
+ ld r0, -X
+ eor \param, r0
+ .endr
+1:
+ dec CTR
+ brne 2f
+ set
+2:
+ ldi r31, hi8(aes_invsbox)
+ /* substitute and invShift */
+ .irp param, ST00, ST10, ST20, ST30
+ mov r30, \param
+ lpm \param, Z
+ .endr
+ mov r30, ST31
+ lpm T0, Z
+ mov r30, ST21
+ lpm ST31, Z
+ mov r30, ST11
+ lpm ST21, Z
+ mov r30, ST01
+ lpm ST11, Z
+ mov ST01, T0
+
+ mov r30, ST32
+ lpm T0, Z
+ mov r30, ST22
+ lpm T1,Z
+ mov r30, ST12
+ lpm ST32, Z
+ mov r30, ST02
+ lpm ST22, Z
+ mov ST12, T0
+ mov ST02, T1
+
+ mov r30, ST03
+ lpm T0, Z
+ mov r30, ST13
+ lpm ST03, Z
+ mov r30, ST23
+ lpm ST13, Z
+ mov r30, ST33
+ lpm ST23, Z
+ mov ST33, T0
+
+ /* key addition */
+ .irp param, ST33, ST32, ST31, ST30, ST23, ST22, ST21, ST20, ST13, ST12, ST11, ST10, ST03, ST02, ST01, ST00
+ ld r0, -X
+ eor \param, r0
+ .endr
+ brtc 2f
+exit:
+ pop r31
+ pop r30
+ st Z+, ST00
+ st Z+, ST01
+ st Z+, ST02
+ st Z+, ST03
+ st Z+, ST10
+ st Z+, ST11
+ st Z+, ST12
+ st Z+, ST13
+ st Z+, ST20
+ st Z+, ST21
+ st Z+, ST22
+ st Z+, ST23
+ st Z+, ST30
+ st Z+, ST31
+ st Z+, ST32
+ st Z+, ST33
+ pop r29
+ pop r28
+ pop_range 2, 17
+ ret
+2:
+ /* inv column (row) mixing*/
+ /* invMixCol (Row) 1 */
+ /* preparing */
+ ldi r31, hi8(lut_gf256mul_0x09)
+ mov T0, ST03
+ eor T0, ST02 ; T0 = t
+ mov T1, ST00
+ eor T1, ST01 ; T1 = u
+ mov r30, T0
+ eor r30, T1
+ lpm T2, Z ; T2 = v'
+
+ ldi r31, hi8(lut_gf256mul_0x04)
+ mov r30, ST02
+ eor r30, ST00
+ lpm T3, Z
+ eor T3, T2; T3 = w
+
+ mov r30, ST03
+ eor r30, ST01
+ lpm P, Z ; T2 = v
+ eor T2, P
+
+ /* now the big move */
+ mov T4, ST00
+ eor T4, ST03
+ lsl T4
+ brcc 3f
+ eor T4, xREDUCER
+3: eor T4, T2
+ eor ST03, T4
+
+ mov T4, ST02
+ eor T4, ST01
+ lsl T4
+ brcc 3f
+ eor T4, xREDUCER
+3: eor T4, T2
+ eor ST01, T4
+
+ lsl T0
+ brcc 3f
+ eor T0, xREDUCER
+3: eor T0, T3
+ eor ST02, T0
+
+ lsl T1
+ brcc 3f
+ eor T1, xREDUCER
+3: eor T1, T3
+ eor ST00, T1
+
+ /* invMixCol (Row) 2 */
+ /* preparing */
+ ldi r31, hi8(lut_gf256mul_0x09)
+ mov T0, ST13
+ eor T0, ST12 ; T0 = t
+ mov T1, ST10
+ eor T1, ST11 ; T1 = u
+ mov r30, T0
+ eor r30, T1
+
+ lpm T2, Z ; T2 = v'
+
+ ldi r31, hi8(lut_gf256mul_0x04)
+ mov r30, ST12
+ eor r30, ST10
+ lpm T3, Z
+ eor T3, T2; T3 = w
+
+ mov r30, ST13
+ eor r30, ST11
+ lpm P, Z
+ eor T2, P ; T2 = v
+
+ /* now the big move */
+ mov T4, ST10
+ eor T4, ST13
+ lsl T4
+ brcc 3f
+ eor T4, xREDUCER
+3: eor T4, T2
+ eor ST13, T4
+
+ mov T4, ST12
+ eor T4, ST11
+ lsl T4
+ brcc 3f
+ eor T4, xREDUCER
+3: eor T4, T2
+ eor ST11, T4
+
+ lsl T0
+ brcc 3f
+ eor T0, xREDUCER
+3: eor T0, T3
+ eor ST12, T0
+
+ lsl T1
+ brcc 3f
+ eor T1, xREDUCER
+3: eor T1, T3
+ eor ST10, T1
+
+ /* invMixCol (Row) 2 */
+ /* preparing */
+ ldi r31, hi8(lut_gf256mul_0x09)
+ mov T0, ST23
+ eor T0, ST22 ; T0 = t
+ mov T1, ST20
+ eor T1, ST21 ; T1 = u
+ mov r30, T0
+ eor r30, T1
+
+ lpm T2, Z ; T2 = v'
+
+ ldi r31, hi8(lut_gf256mul_0x04)
+ mov r30, ST22
+ eor r30, ST20
+ lpm T3, Z
+ eor T3, T2; T3 = w
+
+ mov r30, ST23
+ eor r30, ST21
+ lpm P, Z
+ eor T2, P ; T2 = v
+
+ /* now the big move */
+ mov T4, ST20
+ eor T4, ST23
+ lsl T4
+ brcc 3f
+ eor T4, xREDUCER
+3: eor T4, T2
+ eor ST23, T4
+
+ mov T4, ST22
+ eor T4, ST21
+ lsl T4
+ brcc 3f
+ eor T4, xREDUCER
+3: eor T4, T2
+ eor ST21, T4
+
+ lsl T0
+ brcc 3f
+ eor T0, xREDUCER
+3: eor T0, T3
+ eor ST22, T0
+
+ lsl T1
+ brcc 3f
+ eor T1, xREDUCER
+3: eor T1, T3
+ eor ST20, T1
+
+ /* invMixCol (Row) 3 */
+ /* preparing */
+ ldi r31, hi8(lut_gf256mul_0x09)
+ mov T0, ST33
+ eor T0, ST32 ; T0 = t
+ mov T1, ST30
+ eor T1, ST31 ; T1 = u
+ mov r30, T0
+ eor r30, T1
+
+ lpm T2, Z ; T2 = v'
+
+ ldi r31, hi8(lut_gf256mul_0x04)
+ mov r30, ST32
+ eor r30, ST30
+ lpm T3, Z
+ eor T3, T2; T3 = w
+
+ mov r30, ST33
+ eor r30, ST31
+ lpm P, Z
+ eor T2, P ; T2 = v
+
+ /* now the big move */
+ mov T4, ST30
+ eor T4, ST33
+ lsl T4
+ brcc 3f
+ eor T4, xREDUCER
+3: eor T4, T2
+ eor ST33, T4
+
+ mov T4, ST32
+ eor T4, ST31
+ lsl T4
+ brcc 3f
+ eor T4, xREDUCER
+3: eor T4, T2
+ eor ST31, T4
+
+ lsl T0
+ brcc 3f
+ eor T0, xREDUCER
+3: eor T0, T3
+ eor ST32, T0
+
+ lsl T1
+ brcc 3f
+ eor T1, xREDUCER
+3: eor T1, T3
+ eor ST30, T1
+
+ rjmp 1b
+
+.balign 256
+
+lut_gf256mul_0x09:
+.byte 0x00, 0x09, 0x12, 0x1B, 0x24, 0x2D, 0x36, 0x3F
+.byte 0x48, 0x41, 0x5A, 0x53, 0x6C, 0x65, 0x7E, 0x77
+.byte 0x90, 0x99, 0x82, 0x8B, 0xB4, 0xBD, 0xA6, 0xAF
+.byte 0xD8, 0xD1, 0xCA, 0xC3, 0xFC, 0xF5, 0xEE, 0xE7
+.byte 0x3B, 0x32, 0x29, 0x20, 0x1F, 0x16, 0x0D, 0x04
+.byte 0x73, 0x7A, 0x61, 0x68, 0x57, 0x5E, 0x45, 0x4C
+.byte 0xAB, 0xA2, 0xB9, 0xB0, 0x8F, 0x86, 0x9D, 0x94
+.byte 0xE3, 0xEA, 0xF1, 0xF8, 0xC7, 0xCE, 0xD5, 0xDC
+.byte 0x76, 0x7F, 0x64, 0x6D, 0x52, 0x5B, 0x40, 0x49
+.byte 0x3E, 0x37, 0x2C, 0x25, 0x1A, 0x13, 0x08, 0x01
+.byte 0xE6, 0xEF, 0xF4, 0xFD, 0xC2, 0xCB, 0xD0, 0xD9
+.byte 0xAE, 0xA7, 0xBC, 0xB5, 0x8A, 0x83, 0x98, 0x91
+.byte 0x4D, 0x44, 0x5F, 0x56, 0x69, 0x60, 0x7B, 0x72
+.byte 0x05, 0x0C, 0x17, 0x1E, 0x21, 0x28, 0x33, 0x3A
+.byte 0xDD, 0xD4, 0xCF, 0xC6, 0xF9, 0xF0, 0xEB, 0xE2
+.byte 0x95, 0x9C, 0x87, 0x8E, 0xB1, 0xB8, 0xA3, 0xAA
+.byte 0xEC, 0xE5, 0xFE, 0xF7, 0xC8, 0xC1, 0xDA, 0xD3
+.byte 0xA4, 0xAD, 0xB6, 0xBF, 0x80, 0x89, 0x92, 0x9B
+.byte 0x7C, 0x75, 0x6E, 0x67, 0x58, 0x51, 0x4A, 0x43
+.byte 0x34, 0x3D, 0x26, 0x2F, 0x10, 0x19, 0x02, 0x0B
+.byte 0xD7, 0xDE, 0xC5, 0xCC, 0xF3, 0xFA, 0xE1, 0xE8
+.byte 0x9F, 0x96, 0x8D, 0x84, 0xBB, 0xB2, 0xA9, 0xA0
+.byte 0x47, 0x4E, 0x55, 0x5C, 0x63, 0x6A, 0x71, 0x78
+.byte 0x0F, 0x06, 0x1D, 0x14, 0x2B, 0x22, 0x39, 0x30
+.byte 0x9A, 0x93, 0x88, 0x81, 0xBE, 0xB7, 0xAC, 0xA5
+.byte 0xD2, 0xDB, 0xC0, 0xC9, 0xF6, 0xFF, 0xE4, 0xED
+.byte 0x0A, 0x03, 0x18, 0x11, 0x2E, 0x27, 0x3C, 0x35
+.byte 0x42, 0x4B, 0x50, 0x59, 0x66, 0x6F, 0x74, 0x7D
+.byte 0xA1, 0xA8, 0xB3, 0xBA, 0x85, 0x8C, 0x97, 0x9E
+.byte 0xE9, 0xE0, 0xFB, 0xF2, 0xCD, 0xC4, 0xDF, 0xD6
+.byte 0x31, 0x38, 0x23, 0x2A, 0x15, 0x1C, 0x07, 0x0E
+.byte 0x79, 0x70, 0x6B, 0x62, 0x5D, 0x54, 0x4F, 0x46
+
+lut_gf256mul_0x04:
+.byte 0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C
+.byte 0x20, 0x24, 0x28, 0x2C, 0x30, 0x34, 0x38, 0x3C
+.byte 0x40, 0x44, 0x48, 0x4C, 0x50, 0x54, 0x58, 0x5C
+.byte 0x60, 0x64, 0x68, 0x6C, 0x70, 0x74, 0x78, 0x7C
+.byte 0x80, 0x84, 0x88, 0x8C, 0x90, 0x94, 0x98, 0x9C
+.byte 0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC
+.byte 0xC0, 0xC4, 0xC8, 0xCC, 0xD0, 0xD4, 0xD8, 0xDC
+.byte 0xE0, 0xE4, 0xE8, 0xEC, 0xF0, 0xF4, 0xF8, 0xFC
+.byte 0x1B, 0x1F, 0x13, 0x17, 0x0B, 0x0F, 0x03, 0x07
+.byte 0x3B, 0x3F, 0x33, 0x37, 0x2B, 0x2F, 0x23, 0x27
+.byte 0x5B, 0x5F, 0x53, 0x57, 0x4B, 0x4F, 0x43, 0x47
+.byte 0x7B, 0x7F, 0x73, 0x77, 0x6B, 0x6F, 0x63, 0x67
+.byte 0x9B, 0x9F, 0x93, 0x97, 0x8B, 0x8F, 0x83, 0x87
+.byte 0xBB, 0xBF, 0xB3, 0xB7, 0xAB, 0xAF, 0xA3, 0xA7
+.byte 0xDB, 0xDF, 0xD3, 0xD7, 0xCB, 0xCF, 0xC3, 0xC7
+.byte 0xFB, 0xFF, 0xF3, 0xF7, 0xEB, 0xEF, 0xE3, 0xE7
+.byte 0x36, 0x32, 0x3E, 0x3A, 0x26, 0x22, 0x2E, 0x2A
+.byte 0x16, 0x12, 0x1E, 0x1A, 0x06, 0x02, 0x0E, 0x0A
+.byte 0x76, 0x72, 0x7E, 0x7A, 0x66, 0x62, 0x6E, 0x6A
+.byte 0x56, 0x52, 0x5E, 0x5A, 0x46, 0x42, 0x4E, 0x4A
+.byte 0xB6, 0xB2, 0xBE, 0xBA, 0xA6, 0xA2, 0xAE, 0xAA
+.byte 0x96, 0x92, 0x9E, 0x9A, 0x86, 0x82, 0x8E, 0x8A
+.byte 0xF6, 0xF2, 0xFE, 0xFA, 0xE6, 0xE2, 0xEE, 0xEA
+.byte 0xD6, 0xD2, 0xDE, 0xDA, 0xC6, 0xC2, 0xCE, 0xCA
+.byte 0x2D, 0x29, 0x25, 0x21, 0x3D, 0x39, 0x35, 0x31
+.byte 0x0D, 0x09, 0x05, 0x01, 0x1D, 0x19, 0x15, 0x11
+.byte 0x6D, 0x69, 0x65, 0x61, 0x7D, 0x79, 0x75, 0x71
+.byte 0x4D, 0x49, 0x45, 0x41, 0x5D, 0x59, 0x55, 0x51
+.byte 0xAD, 0xA9, 0xA5, 0xA1, 0xBD, 0xB9, 0xB5, 0xB1
+.byte 0x8D, 0x89, 0x85, 0x81, 0x9D, 0x99, 0x95, 0x91
+.byte 0xED, 0xE9, 0xE5, 0xE1, 0xFD, 0xF9, 0xF5, 0xF1
+.byte 0xCD, 0xC9, 0xC5, 0xC1, 0xDD, 0xD9, 0xD5, 0xD1
+
--- /dev/null
+/* aes_dec.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes_dec.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-30
+ * \license GPLv3 or later
+ *
+ */
+#ifndef AES_DEC_H_
+#define AES_DEC_H_
+#include "aes_types.h"
+#include <stdint.h>
+
+
+void aes_decrypt_core(aes_cipher_state_t* state,const aes_genctx_t* ks, uint8_t rounds);
+
+
+#endif
--- /dev/null
+/* aes_enc-asm.S */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008, 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes_enc-asm.S
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-10
+ * \license GPLv3 or later
+ *
+ */
+
+#include "avr-asm-macros.S"
+
+
+/*
+ * param a: r24
+ * param b: r22
+ * param reducer: r0
+ */
+A = 28
+B = 29
+P = 0
+xREDUCER = 25
+
+.global aes256_enc
+aes256_enc:
+ ldi r20, 14
+ rjmp aes_encrypt_core
+
+.global aes192_enc
+aes192_enc:
+ ldi r20, 12
+ rjmp aes_encrypt_core
+
+.global aes128_enc
+aes128_enc:
+ ldi r20, 10
+
+
+/*
+ void aes_encrypt_core(aes_cipher_state_t* state, const aes_genctx_t* ks, uint8_t rounds)
+*/
+T0= 2
+T1= 3
+T2= 4
+T3= 5
+SBOX_SAVE0 = 6
+SBOX_SAVE1 = 7
+ST00 = 8
+ST01 = 9
+ST02 = 10
+ST03 = 11
+ST10 = 12
+ST11 = 13
+ST12 = 14
+ST13 = 15
+ST20 = 16
+ST21 = 17
+ST22 = 18
+ST23 = 19
+ST30 = 20
+ST31 = 21
+ST32 = 22
+ST33 = 23
+CTR = 24
+/*
+ * param state: r24:r25
+ * param ks: r22:r23
+ * param rounds: r20
+ */
+.global aes_encrypt_core
+aes_encrypt_core:
+ push_range 2, 17
+ push r28
+ push r29
+ push r24
+ push r25
+ movw r26, r22
+ movw r30, r24
+ mov CTR, r20
+ clt
+
+ .irp param,ST00, ST01, ST02, ST03, ST10, ST11, ST12, ST13, ST20, ST21, ST22, ST23, ST30, ST31, ST32, ST33
+ ld \param, Z+
+ .endr
+
+ ldi xREDUCER, 0x1b /* load reducer */
+ ldi r31, hi8(aes_sbox)
+
+ /* key whitening */
+1:
+ .irp param,ST00, ST01, ST02, ST03, ST10, ST11, ST12, ST13, ST20, ST21, ST22, ST23, ST30, ST31, ST32, ST33
+ ld r0, X+
+ eor \param, r0
+ .endr
+
+ brtc 2f
+exit:
+ pop r31
+ pop r30
+ st Z+, ST00
+ st Z+, ST01
+ st Z+, ST02
+ st Z+, ST03
+ st Z+, ST10
+ st Z+, ST11
+ st Z+, ST12
+ st Z+, ST13
+ st Z+, ST20
+ st Z+, ST21
+ st Z+, ST22
+ st Z+, ST23
+ st Z+, ST30
+ st Z+, ST31
+ st Z+, ST32
+ st Z+, ST33
+ pop r29
+ pop r28
+ pop_range 2, 17
+ ret
+
+2: dec CTR
+ brne 3f
+ set
+3:
+
+ /* encryption loop */
+
+ /* SBOX substitution and shifting */
+ mov r30, ST00
+ lpm ST00, Z
+ mov r30, ST10
+ lpm ST10, Z
+ mov r30, ST20
+ lpm ST20, Z
+ mov r30, ST30
+ lpm ST30, Z
+
+ mov r30, ST01
+ lpm T0, Z
+ mov r30, ST11
+ lpm ST01, Z
+ mov r30, ST21
+ lpm ST11, Z
+ mov r30, ST31
+ lpm ST21, Z
+ mov ST31, T0
+
+ mov r30, ST02
+ lpm T0, Z
+ mov r30, ST12
+ lpm T1, Z
+ mov r30, ST22
+ lpm ST02, Z
+ mov r30, ST32
+ lpm ST12, Z
+ mov ST22, T0
+ mov ST32, T1
+
+ mov r30, ST03
+ lpm T0, Z
+ mov r30, ST33
+ lpm ST03, Z
+ mov r30, ST23
+ lpm ST33, Z
+ mov r30, ST13
+ lpm ST23, Z
+ mov ST13, T0
+
+ /* mixcols (or rows in our case) */
+ brtc 2f
+ rjmp 1b
+2:
+ /* mixrow 1 */
+ mov r0, ST02
+ eor r0, ST03
+ mov T2, r0
+
+ mov T0, ST00
+ eor ST00, ST01
+ eor r0, ST00
+ lsl ST00
+ brcc 3f
+ eor ST00, xREDUCER
+3: eor ST00, r0
+ eor ST00, T0
+
+ mov T1, ST01
+ eor T1, ST02
+ lsl T1
+ brcc 3f
+ eor T1, xREDUCER
+3: eor T1, r0
+ eor ST01, T1
+
+ lsl T2
+ brcc 3f
+ eor T2, xREDUCER
+3: eor T2, r0
+ eor ST02, T2
+
+ eor T0, ST03
+ lsl T0
+ brcc 3f
+ eor T0, xREDUCER
+3: eor T0, r0
+ eor ST03, T0
+
+ /* mixrow 2 */
+ mov r0, ST12
+ eor r0, ST13
+ mov T2, r0
+
+ mov T0, ST10
+ eor ST10, ST11
+ eor r0, ST10
+ lsl ST10
+ brcc 3f
+ eor ST10, xREDUCER
+3: eor ST10, r0
+ eor ST10, T0
+
+ mov T1, ST11
+ eor T1, ST12
+ lsl T1
+ brcc 3f
+ eor T1, xREDUCER
+3: eor T1, r0
+ eor ST11, T1
+
+ lsl T2
+ brcc 3f
+ eor T2, xREDUCER
+3: eor T2, r0
+ eor ST12, T2
+
+ eor T0, ST13
+ lsl T0
+ brcc 3f
+ eor T0, xREDUCER
+3: eor T0, r0
+ eor ST13, T0
+
+ /* mixrow 3 */
+ mov r0, ST22
+ eor r0, ST23
+ mov T2, r0
+
+ mov T0, ST20
+ eor ST20, ST21
+ eor r0, ST20
+ lsl ST20
+ brcc 3f
+ eor ST20, xREDUCER
+3: eor ST20, r0
+ eor ST20, T0
+
+ mov T1, ST21
+ eor T1, ST22
+ lsl T1
+ brcc 3f
+ eor T1, xREDUCER
+3: eor T1, r0
+ eor ST21, T1
+
+ lsl T2
+ brcc 3f
+ eor T2, xREDUCER
+3: eor T2, r0
+ eor ST22, T2
+
+ eor T0, ST23
+ lsl T0
+ brcc 3f
+ eor T0, xREDUCER
+3: eor T0, r0
+ eor ST23, T0
+
+ /* mixrow 4 */
+ mov r0, ST32
+ eor r0, ST33
+ mov T2, r0
+
+ mov T0, ST30
+ eor ST30, ST31
+ eor r0, ST30
+ lsl ST30
+ brcc 3f
+ eor ST30, xREDUCER
+3: eor ST30, r0
+ eor ST30, T0
+
+ mov T1, ST31
+ eor T1, ST32
+ lsl T1
+ brcc 3f
+ eor T1, xREDUCER
+3: eor T1, r0
+ eor ST31, T1
+
+ lsl T2
+ brcc 3f
+ eor T2, xREDUCER
+3: eor T2, r0
+ eor ST32, T2
+
+ eor T0, ST33
+ lsl T0
+ brcc 3f
+ eor T0, xREDUCER
+3: eor T0, r0
+ eor ST33, T0
+ /* mix colums (rows) done */
+
+ /* add key*/
+ rjmp 1b
+
+
+
+
+
+
+
+
+
--- /dev/null
+/* aes_enc.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes_enc.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-30
+ * \license GPLv3 or later
+ *
+ */
+#ifndef AES_ENC_H_
+#define AES_ENC_H_
+#include "aes_types.h"
+#include <stdint.h>
+
+
+void aes_encrypt_core(aes_cipher_state_t* state, const aes_genctx_t* ks, uint8_t rounds);
+
+
+#endif
--- /dev/null
+/* aes_sbox-asm.S */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008, 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes_dec-asm.S
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-10
+ * \license GPLv3 or later
+ *
+ */
+.balign 256
+.global aes_invsbox
+aes_invsbox:
+.byte 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb
+.byte 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb
+.byte 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e
+.byte 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25
+.byte 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92
+.byte 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84
+.byte 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06
+.byte 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b
+.byte 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73
+.byte 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e
+.byte 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b
+.byte 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4
+.byte 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f
+.byte 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef
+.byte 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61
+.byte 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
--- /dev/null
+/* aes_invsbox.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes_invsbox.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-30
+ * \license GPLv3 or later
+ *
+ */
+#ifndef AES_INVSBOX_H_
+#define AES_INVSBOX_H_
+#include <stdint.h>
+
+extern uint8_t aes_invsbox[];
+
+#endif
--- /dev/null
+/* aes_keyschedule-asm */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008, 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes_keyschedule-asm.S
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-09
+ * \license GPLv3 or later
+ *
+ */
+
+#include "avr-asm-macros.S"
+
+.global aes256_init
+aes256_init:
+ movw r20, r22
+ ldi r23, hi8(256)
+ ldi r22, lo8(256)
+ rjmp aes_init
+
+.global aes192_init
+aes192_init:
+ movw r20, r22
+ ldi r23, hi8(192)
+ ldi r22, lo8(192)
+ rjmp aes_init
+
+.global aes128_init
+aes128_init:
+ movw r20, r22
+ clr r23
+ ldi r22, 128
+
+/*
+void aes_init(const void* key, uint16_t keysize_b, aes_genctx_t* ctx){
+ uint8_t hi,i,nk, next_nk;
+ uint8_t rc=1;
+ uint8_t tmp[4];
+ nk=keysize_b>>5; / * 4, 6, 8 * /
+ hi=4*(nk+6+1);
+ memcpy(ctx, key, keysize_b/8);
+ next_nk = nk;
+ for(i=nk;i<hi;++i){
+ *((uint32_t*)tmp) = ((uint32_t*)(ctx->key[0].ks))[i-1];
+ if(i!=next_nk){
+ if(nk==8 && i%8==4){
+ tmp[0] = pgm_read_byte(aes_sbox+tmp[0]);
+ tmp[1] = pgm_read_byte(aes_sbox+tmp[1]);
+ tmp[2] = pgm_read_byte(aes_sbox+tmp[2]);
+ tmp[3] = pgm_read_byte(aes_sbox+tmp[3]);
+ }
+ } else {
+ next_nk += nk;
+ aes_rotword(tmp);
+ tmp[0] = pgm_read_byte(aes_sbox+tmp[0]);
+ tmp[1] = pgm_read_byte(aes_sbox+tmp[1]);
+ tmp[2] = pgm_read_byte(aes_sbox+tmp[2]);
+ tmp[3] = pgm_read_byte(aes_sbox+tmp[3]);
+ tmp[0] ^= rc;
+ rc<<=1;
+ }
+ ((uint32_t*)(ctx->key[0].ks))[i] = ((uint32_t*)(ctx->key[0].ks))[i-nk]
+ ^ *((uint32_t*)tmp);
+ }
+}
+*/
+
+SBOX_SAVE0 = 14
+SBOX_SAVE1 = 15
+XRC = 17
+NK = 22
+C1 = 18
+NEXT_NK = 19
+HI = 23
+T0 = 20
+T1 = 21
+T2 = 24
+T3 = 25
+/*
+ * param key: r24:r25
+ * param keysize_b: r22:r23
+ * param ctx: r20:r21
+ */
+.global aes_init
+aes_init:
+ push_range 14, 17
+ push r28
+ push r29
+ movw r30, r20
+ movw r28, r20
+ movw r26, r24
+ lsr r23
+ ror r22
+ lsr r22
+ lsr r22 /* r22 contains keysize_b/8 */
+ mov C1, r22
+
+1: /* copy key to ctx */
+ ld r0, X+
+ st Z+, r0
+ dec C1
+ brne 1b
+
+ lsr NK
+ lsr NK
+ bst NK,3 /* set T if NK==8 */
+ mov NEXT_NK, NK
+ mov HI, NK
+ subi HI, -7
+ lsl HI
+ lsl HI
+ movw r26, r30
+ sbiw r26, 4
+ mov C1, NK
+ ldi r30, lo8(aes_sbox)
+ ldi r31, hi8(aes_sbox)
+ movw SBOX_SAVE0, r30
+ ldi XRC, 1
+1:
+ ld T0, X+
+ ld T1, X+
+ ld T2, X+
+ ld T3, X+
+ cp NEXT_NK, C1
+ breq 2f
+ brtc 5f
+ mov r16, C1
+ andi r16, 0x07
+ cpi r16, 0x04
+ brne 5f
+ movw r30, SBOX_SAVE0
+ add r30, T0
+ adc r31, r1
+ lpm T0, Z
+ movw r30, SBOX_SAVE0
+ add r30, T1
+ adc r31, r1
+ lpm T1, Z
+ movw r30, SBOX_SAVE0
+ add r30, T2
+ adc r31, r1
+ lpm T2, Z
+ movw r30, SBOX_SAVE0
+ add r30, T3
+ adc r31, r1
+ lpm T3, Z
+ rjmp 5f
+2:
+ add NEXT_NK, NK
+ movw r30, SBOX_SAVE0
+ add r30, T0
+ adc r31, r1
+ lpm r16, Z
+ movw r30, SBOX_SAVE0
+ add r30, T1
+ adc r31, r1
+ lpm T0, Z
+ movw r30, SBOX_SAVE0
+ add r30, T2
+ adc r31, r1
+ lpm T1, Z
+ movw r30, SBOX_SAVE0
+ add r30, T3
+ adc r31, r1
+ lpm T2, Z
+ mov T3, r16
+ eor T0, XRC
+ lsl XRC
+ brcc 3f
+ ldi XRC, 0x1b
+3:
+5:
+ movw r30, r26
+
+ ld r0, Y+
+ eor r0, T0
+ st Z+, r0
+ ld r0, Y+
+ eor r0 ,T1
+ st Z+, r0
+ ld r0, Y+
+ eor r0, T2
+ st Z+, r0
+ ld r0, Y+
+ eor r0, T3
+ st Z+, r0
+
+/*
+ st Z+, T0
+ st Z+, T1
+ st Z+, T2
+ st Z+, T3
+*/
+
+ inc C1
+ cp C1, HI
+ breq 6f
+ rjmp 1b
+6:
+
+ clt
+ pop r29
+ pop r28
+ pop_range 14, 17
+ ret
+
+
+
+
--- /dev/null
+/* aes_keyschedule.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes_keyschedule.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-30
+ * \license GPLv3 or later
+ * \ingroup AES
+ */
+
+
+#ifndef AES_KEYSCHEDULE_H_
+#define AES_KEYSCHEDULE_H_
+
+#include "aes_types.h"
+/**
+ * \brief initialize the keyschedule
+ *
+ * This function computes the keyschedule from a given key with a given length
+ * and stores it in the context variable
+ * \param key pointer to the key material
+ * \param keysize_b length of the key in bits (valid are 128, 192 and 256)
+ * \param ctx pointer to the context where the keyschedule should be stored
+ */
+void aes_init(const void* key, uint16_t keysize_b, aes_genctx_t* ctx);
+
+/**
+ * \brief initialize the keyschedule for 128 bit key
+ *
+ * This function computes the keyschedule from a given 128 bit key
+ * and stores it in the context variable
+ * \param key pointer to the key material
+ * \param ctx pointer to the context where the keyschedule should be stored
+ */
+void aes128_init(const void* key, aes128_ctx_t* ctx);
+
+/**
+ * \brief initialize the keyschedule for 192 bit key
+ *
+ * This function computes the keyschedule from a given 192 bit key
+ * and stores it in the context variable
+ * \param key pointer to the key material
+ * \param ctx pointer to the context where the keyschedule should be stored
+ */
+void aes192_init(const void* key, aes192_ctx_t* ctx);
+
+/**
+ * \brief initialize the keyschedule for 256 bit key
+ *
+ * This function computes the keyschedule from a given 256 bit key
+ * and stores it in the context variable
+ * \param key pointer to the key material
+ * \param ctx pointer to the context where the keyschedule should be stored
+ */
+void aes256_init(const void* key, aes256_ctx_t* ctx);
+
+#endif /* AES_KEYSCHEDULE_H_ */
+
--- /dev/null
+/* aes_sbox-asm.S */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008, 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes_dec-asm.S
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-10
+ * \license GPLv3 or later
+ *
+ */
+
+.balign 256
+.global aes_sbox
+aes_sbox:
+.byte 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76
+.byte 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0
+.byte 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15
+.byte 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75
+.byte 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84
+.byte 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf
+.byte 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8
+.byte 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2
+.byte 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73
+.byte 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb
+.byte 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79
+.byte 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08
+.byte 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a
+.byte 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e
+.byte 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf
+.byte 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
+
--- /dev/null
+/* aes_sbox.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes_sbox.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-30
+ * \license GPLv3 or later
+ *
+ */
+#ifndef AES_SBOX_H_
+#define AES_SBOX_H_
+#include <stdint.h>
+
+extern uint8_t aes_sbox[];
+
+#endif
--- /dev/null
+/* aes.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file aes_types.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2008-12-30
+ * \license GPLv3 or later
+ *
+ */
+#ifndef AES_TYPES_H_
+#define AES_TYPES_H_
+
+#include <stdint.h>
+
+typedef struct{
+ uint8_t ks[16];
+} aes_roundkey_t;
+
+typedef struct{
+ aes_roundkey_t key[10+1];
+} aes128_ctx_t;
+
+typedef struct{
+ aes_roundkey_t key[12+1];
+} aes192_ctx_t;
+
+typedef struct{
+ aes_roundkey_t key[14+1];
+} aes256_ctx_t;
+
+typedef struct{
+ aes_roundkey_t key[1]; /* just to avoid the warning */
+} aes_genctx_t;
+
+typedef struct{
+ uint8_t s[16];
+} aes_cipher_state_t;
+
+#endif
--- /dev/null
+/* avr-asm-macros.S */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * File: avr-asm-macros.S
+ * Author: Daniel Otte
+ * Date: 2008-08-13
+ * License: GPLv3 or later
+ * Description: some macros which are quite usefull
+ *
+ */
+
+//#ifndef AVR_ASM_MACROS__S__
+//#define AVR_ASM_MACROS__S__
+//#include <avr/io.h>
+
+/*******************************************************************************
+* MACRO SECTION *
+*******************************************************************************/
+
+.macro push_ p1:req, p2:vararg
+ push \p1
+.ifnb \p2
+ push_ \p2
+.endif
+.endm
+
+.macro pop_ p1:req, p2:vararg
+ pop \p1
+.ifnb \p2
+ pop_ \p2
+.endif
+.endm
+
+.macro push_range from:req, to:req
+ push \from
+.if \to-\from
+ push_range "(\from+1)",\to
+.endif
+.endm
+
+.macro pop_range from:req, to:req
+ pop \to
+.if \to-\from
+ pop_range \from,"(\to-1)"
+.endif
+.endm
+
+.macro stack_alloc size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ sbiw \reg1, \size
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+.macro stack_free size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ adiw \reg1, \size
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+
+.macro stack_alloc_large size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ subi \reg1, lo8(\size)
+ sbci \reg2, hi8(\size)
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+.macro stack_free_large size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ adiw \reg1, 63
+ adiw \reg1, (\size-63)
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+.macro stack_free_large2 size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ adiw \reg1, 63
+ adiw \reg1, 63
+ adiw \reg1, (\size-63*2)
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+.macro stack_free_large3 size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ push r16
+ push r17
+ ldi r16, lo8(\size)
+ ldi r17, hi8(\size)
+ add \reg1, r16
+ adc \reg2, r17
+ pop r17
+ pop r16
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+
+/*******************************************************************************
+* END of MACRO SECTION *
+*******************************************************************************/
+
+
+//#endif /* AVR_ASM_MACROS__S__ */
+
--- /dev/null
+/* avr-asm-macros.S */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * File: avr-asm-macros.S
+ * Author: Daniel Otte
+ * Date: 2008-08-13
+ * License: GPLv3 or later
+ * Description: some macros which are quite usefull
+ *
+ */
+
+//#ifndef AVR_ASM_MACROS__S__
+//#define AVR_ASM_MACROS__S__
+#include <avr/io.h>
+
+/*******************************************************************************
+* MACRO SECTION *
+*******************************************************************************/
+
+.macro push_ p1:req, p2:vararg
+ push \p1
+.ifnb \p2
+ push_ \p2
+.endif
+.endm
+
+.macro pop_ p1:req, p2:vararg
+ pop \p1
+.ifnb \p2
+ pop_ \p2
+.endif
+.endm
+
+.macro push_range from:req, to:req
+ push \from
+.if \to-\from
+ push_range "(\from+1)",\to
+.endif
+.endm
+
+.macro pop_range from:req, to:req
+ pop \to
+.if \to-\from
+ pop_range \from,"(\to-1)"
+.endif
+.endm
+
+.macro stack_alloc size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ sbiw \reg1, \size
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+.macro stack_free size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ adiw \reg1, \size
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+
+.macro stack_alloc_large size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ subi \reg1, lo8(\size)
+ sbci \reg2, hi8(\size)
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+.macro stack_free_large size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ adiw \reg1, 63
+ adiw \reg1, (\size-63)
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+.macro stack_free_large2 size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ adiw \reg1, 63
+ adiw \reg1, 63
+ adiw \reg1, (\size-63*2)
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+.macro stack_free_large3 size:req, reg1=r30, reg2=r31
+ in r0, _SFR_IO_ADDR(SREG)
+ in \reg1, _SFR_IO_ADDR(SPL)
+ in \reg2, _SFR_IO_ADDR(SPH)
+ push r16
+ push r17
+ ldi r16, lo8(\size)
+ ldi r17, hi8(\size)
+ add \reg1, r16
+ adc \reg2, r17
+ pop r17
+ pop r16
+ cli
+ out _SFR_IO_ADDR(SPH), \reg2
+ out _SFR_IO_ADDR(SREG), r0
+ out _SFR_IO_ADDR(SPL), \reg1
+.endm
+
+
+/*******************************************************************************
+* END of MACRO SECTION *
+*******************************************************************************/
+
+
+//#endif /* AVR_ASM_MACROS__S__ */
+
--- /dev/null
+/* bcal-basic.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <avr/pgmspace.h>
+#include "blockcipher_descriptor.h"
+#include "keysize_descriptor.h"
+
+uint8_t bcal_cipher_init(const bcdesc_t* cipher_descriptor,
+ const void* key, uint16_t keysize_b, bcgen_ctx_t* ctx){
+ if(!is_valid_keysize_P((PGM_VOID_P)pgm_read_word(&(cipher_descriptor->valid_keysize_desc)),
+ keysize_b)){
+ return 1;
+ }
+ uint8_t flags;
+ bc_init_fpt init_fpt;
+ ctx->desc_ptr = (bcdesc_t*)cipher_descriptor;
+ ctx->keysize = keysize_b;
+ flags = pgm_read_byte(cipher_descriptor->flags);
+ init_fpt.initvoid = (void_fpt)(pgm_read_word(&(cipher_descriptor->init.initvoid)));
+ if(init_fpt.initvoid == NULL){
+ if(!(ctx->ctx = malloc((keysize_b+7)/8)))
+ return 2;
+ memcpy(ctx->ctx, key, (keysize_b+7)/8);
+ return 0;
+ }
+ if(!(ctx->ctx = malloc(pgm_read_word(&(cipher_descriptor->ctxsize_B)))))
+ return 3;
+ if((flags&BC_INIT_TYPE)==BC_INIT_TYPE_1){
+ init_fpt.init1((void*)key, (ctx->ctx));
+ }else{
+ init_fpt.init2((void*)key, keysize_b, (ctx->ctx));
+ }
+ return 0;
+}
+
+void bcal_cipher_free(bcgen_ctx_t* ctx){
+ if(!ctx)
+ return;
+ bc_free_fpt free_fpt;
+ free_fpt = (bc_free_fpt)(pgm_read_word(&(ctx->desc_ptr->free)));
+ if(free_fpt)
+ free_fpt((ctx->ctx));
+ free(ctx->ctx);
+}
+
+void bcal_cipher_enc(void* block, const bcgen_ctx_t* ctx){
+ bc_enc_fpt enc_fpt;
+ enc_fpt.encvoid = (void_fpt)pgm_read_word(&(ctx->desc_ptr->enc.encvoid));
+ if(!enc_fpt.encvoid){
+ /* very bad error, no enciphering function specified */
+ return;
+ }
+ enc_fpt.enc1(block, (ctx->ctx));
+
+}
+
+void bcal_cipher_dec(void* block, const bcgen_ctx_t* ctx){
+ bc_dec_fpt dec_fpt;
+ dec_fpt.decvoid = (void_fpt)pgm_read_word(&(ctx->desc_ptr->dec.decvoid));
+ if(!dec_fpt.decvoid){
+ /* very bad error, no deciphering function specified */
+ return;
+ }
+ dec_fpt.dec1(block, (ctx->ctx));
+}
+
+uint16_t bcal_cipher_getBlocksize_b(const bcdesc_t* desc){
+ return pgm_read_word(&(desc->blocksize_b));
+}
+
+PGM_VOID_P bcal_cipher_getKeysizeDesc(const bcdesc_t* desc){
+ return (PGM_VOID_P)pgm_read_word(&(desc->valid_keysize_desc));
+}
+
+
--- /dev/null
+/* bcal-basic.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef BCAL_BASIC_H_
+#define BCAL_BASIC_H_
+
+#include <stdlib.h>
+#include <stdint.h>
+#include "blockcipher_descriptor.h"
+#include "keysize_descriptor.h"
+#if (defined(AVR))
+#include <avr\pgmspace.h>
+#else
+#include <pgmspace.h>
+#endif
+
+uint8_t bcal_cipher_init(const bcdesc_t* cipher_descriptor,
+ const void* key, uint16_t keysize_b, bcgen_ctx_t* ctx);
+void bcal_cipher_free(bcgen_ctx_t* ctx);
+void bcal_cipher_enc(void* block, const bcgen_ctx_t* ctx);
+void bcal_cipher_dec(void* block, const bcgen_ctx_t* ctx);
+uint16_t bcal_cipher_getBlocksize_b(const bcdesc_t* desc);
+PGM_VOID_P bcal_cipher_getKeysizeDesc(const bcdesc_t* desc);
+#endif /* BCAL_BASIC_H_ */
--- /dev/null
+/* bcal-basic.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef BCAL_BASIC_H_
+#define BCAL_BASIC_H_
+
+#include <stdlib.h>
+#include <stdint.h>
+#include "blockcipher_descriptor.h"
+#include "keysize_descriptor.h"
+#include <avr/pgmspace.h>
+
+uint8_t bcal_cipher_init(const bcdesc_t* cipher_descriptor,
+ const void* key, uint16_t keysize_b, bcgen_ctx_t* ctx);
+void bcal_cipher_free(bcgen_ctx_t* ctx);
+void bcal_cipher_enc(void* block, const bcgen_ctx_t* ctx);
+void bcal_cipher_dec(void* block, const bcgen_ctx_t* ctx);
+uint16_t bcal_cipher_getBlocksize_b(const bcdesc_t* desc);
+PGM_VOID_P bcal_cipher_getKeysizeDesc(const bcdesc_t* desc);
+#endif /* BCAL_BASIC_H_ */
--- /dev/null
+/* bcal-cbc.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2010 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+#include <string.h>
+#include "bcal-cbc.h"
+#include "bcal-basic.h"
+#include "memxor.h"
+
+uint8_t bcal_cbc_init(const bcdesc_t* desc, const void* key, uint16_t keysize_b, bcal_cbc_ctx_t* ctx){
+ ctx->desc = (bcdesc_t*)desc;
+ ctx->blocksize_B = (bcal_cipher_getBlocksize_b(desc)+7)/8;
+ ctx->prev_block = malloc(ctx->blocksize_B);
+
+ if(ctx->prev_block==NULL){
+ return 0x11;
+ }
+ return bcal_cipher_init(desc, key, keysize_b, &(ctx->cctx));
+}
+
+void bcal_cbc_free(bcal_cbc_ctx_t* ctx){
+ bcal_cipher_free(&(ctx->cctx));
+ free(ctx->prev_block);
+}
+
+
+void bcal_cbc_loadIV(const void* iv, bcal_cbc_ctx_t* ctx){
+ if(iv){
+ memcpy(ctx->prev_block, iv, ctx->blocksize_B);
+ }
+}
+
+void bcal_cbc_encNext(void* block, bcal_cbc_ctx_t* ctx){
+ memxor(block, ctx->prev_block, ctx->blocksize_B);
+ bcal_cipher_enc(block, &(ctx->cctx));
+ memcpy(ctx->prev_block, block, ctx->blocksize_B);
+}
+
+void bcal_cbc_decNext(void* block, bcal_cbc_ctx_t* ctx){
+ uint8_t tmp[ctx->blocksize_B];
+ memcpy(tmp, block, ctx->blocksize_B);
+ bcal_cipher_dec(block, &(ctx->cctx));
+ memxor(block, ctx->prev_block, ctx->blocksize_B);
+ memcpy(ctx->prev_block, tmp, ctx->blocksize_B);
+}
+void bcal_cbc_decRand(void* block, const void* prev_block, bcal_cbc_ctx_t* ctx){
+ bcal_cipher_dec(block, &(ctx->cctx));
+ memxor(block, prev_block, ctx->blocksize_B);
+}
+
+void bcal_cbc_encMsg(const void* iv, void* msg, uint16_t msg_blocks, bcal_cbc_ctx_t* ctx){
+ bcal_cbc_loadIV(iv, ctx);
+ while(msg_blocks--){
+ bcal_cbc_encNext(msg, ctx);
+ msg = (uint8_t*)msg + ctx->blocksize_B;
+ }
+}
+
+void bcal_cbc_decMsg(const void* iv, void* msg, uint16_t msg_blocks, bcal_cbc_ctx_t* ctx){
+ msg=(uint8_t*)msg + (msg_blocks-1)*ctx->blocksize_B;
+ while(msg_blocks > 1){
+ bcal_cbc_decRand(msg, (uint8_t*)msg-ctx->blocksize_B, ctx);
+ msg_blocks -= 1;
+ msg=(uint8_t*)msg-ctx->blocksize_B;
+ }
+ bcal_cbc_decRand(msg, iv, ctx);
+}
+
--- /dev/null
+/* bcal-cbc.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2010 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef BCALCBC_H_
+#define BCALCBC_H_
+
+#include <stdint.h>
+#include "blockcipher_descriptor.h"
+#include "bcal-basic.h"
+
+typedef struct{
+ bcdesc_t* desc;
+ bcgen_ctx_t cctx;
+ uint8_t* prev_block;
+ uint8_t blocksize_B;
+} bcal_cbc_ctx_t;
+
+uint8_t bcal_cbc_init(const bcdesc_t* desc, const void* key, uint16_t keysize_b, bcal_cbc_ctx_t* ctx);
+void bcal_cbc_free(bcal_cbc_ctx_t* ctx);
+void bcal_cbc_loadIV(const void* iv, bcal_cbc_ctx_t* ctx);
+void bcal_cbc_encNext(void* block, bcal_cbc_ctx_t* ctx);
+void bcal_cbc_decNext(void* block, bcal_cbc_ctx_t* ctx);
+void bcal_cbc_decRand(void* block, const void* prev_block, bcal_cbc_ctx_t* ctx);
+void bcal_cbc_encMsg(const void* iv, void* msg, uint16_t msg_blocks, bcal_cbc_ctx_t* ctx);
+void bcal_cbc_decMsg(const void* iv, void* msg, uint16_t msg_blocks, bcal_cbc_ctx_t* ctx);
+
+
+#endif /* BCALCBC_H_ */
--- /dev/null
+/* bcal-omac.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2010 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#include <stdint.h>
+#include <string.h>
+#include "bcal-basic.h"
+#include "bcal-cmac.h"
+#include "memxor.h"
+
+
+static uint8_t left_shift_be_block(void* block, uint8_t blocksize_B){
+ uint8_t c1=0, c2;
+ do{
+ --blocksize_B;
+ c2 = (((uint8_t*)block)[blocksize_B])>>7;
+ (((uint8_t*)block)[blocksize_B]) <<= 1;
+ (((uint8_t*)block)[blocksize_B]) |= c1;
+ c1 = c2;
+ }while(blocksize_B);
+ return c1;
+}
+
+static const uint8_t const_128 = 0x87;
+static const uint8_t const_64 = 0x1b;
+
+uint8_t bcal_cmac_init(const bcdesc_t* desc, const void* key, uint16_t keysize_b, bcal_cmac_ctx_t* ctx){
+ uint8_t r;
+ ctx->desc = (bcdesc_t*)desc;
+ ctx->blocksize_B = bcal_cipher_getBlocksize_b(desc)/8;
+ if (ctx->blocksize_B!=128/8 && ctx->blocksize_B!=64/8){
+ return 0x13;
+ }
+ ctx->accu = malloc(ctx->blocksize_B);
+ if(ctx->accu==NULL){
+ return 0x14;
+ }
+ ctx->k1 = malloc(ctx->blocksize_B);
+ if(ctx->k1==NULL){
+ return 0x15;
+ }
+ ctx->k2 = malloc(ctx->blocksize_B);
+ if(ctx->k2==NULL){
+ return 0x16;
+ }
+ ctx->lastblock = malloc(ctx->blocksize_B);
+ if(ctx->lastblock==NULL){
+ return 0x17;
+ }
+ r = bcal_cipher_init(desc, key, keysize_b, &(ctx->cctx));
+ if(r){
+ return r;
+ }
+ if(ctx->blocksize_B==128/8){
+ r = const_128;
+ }else{
+ r = const_64;
+ }
+ /* subkey computation */
+ memset(ctx->accu, 0x00, ctx->blocksize_B);
+ memset(ctx->k1, 0x00, ctx->blocksize_B);
+ bcal_cipher_enc(ctx->k1, &(ctx->cctx));
+ if(left_shift_be_block(ctx->k1, ctx->blocksize_B)){
+ ctx->k1[ctx->blocksize_B-1] ^= r;
+ }
+ memcpy(ctx->k2, ctx->k1, ctx->blocksize_B);
+ if(left_shift_be_block(ctx->k2, ctx->blocksize_B)){
+ ctx->k2[ctx->blocksize_B-1] ^= r;
+ }
+ ctx->last_set=0;
+ return 0;
+}
+
+void bcal_cmac_free(bcal_cmac_ctx_t* ctx){
+ free(ctx->accu);
+ free(ctx->k1);
+ free(ctx->k2);
+ bcal_cipher_free(&(ctx->cctx));
+}
+
+void bcal_cmac_nextBlock (bcal_cmac_ctx_t* ctx, const void* block){
+ if(ctx->last_set){
+ memxor(ctx->accu, ctx->lastblock, ctx->blocksize_B);
+ bcal_cipher_enc(ctx->accu, &(ctx->cctx));
+ }
+ memcpy(ctx->lastblock, block, ctx->blocksize_B);
+ ctx->last_set=1;
+}
+
+
+void bcal_cmac_lastBlock(bcal_cmac_ctx_t* ctx, const void* block, uint16_t length_b){
+ uint16_t blocksize_b;
+ blocksize_b = ctx->blocksize_B*8;
+ while(length_b>=blocksize_b){
+ bcal_cmac_nextBlock(ctx, block);
+ block = (uint8_t*)block + ctx->blocksize_B;
+ length_b -= blocksize_b;
+ }
+ if(ctx->last_set==0){
+ memxor(ctx->accu, block, (length_b+7)/8);
+ memxor(ctx->accu, ctx->k2, ctx->blocksize_B);
+ ctx->accu[length_b/8] ^= 0x80>>(length_b&7);
+ }else{
+ if(length_b==0){
+ memxor(ctx->accu, ctx->lastblock, ctx->blocksize_B);
+ memxor(ctx->accu, ctx->k1, ctx->blocksize_B);
+ }else{
+ memxor(ctx->accu, ctx->lastblock, ctx->blocksize_B);
+ bcal_cipher_enc(ctx->accu, &(ctx->cctx));
+ memxor(ctx->accu, block, (length_b+7)/8);
+ memxor(ctx->accu, ctx->k2, ctx->blocksize_B);
+ ctx->accu[length_b/8] ^= 0x80>>(length_b&7);
+ }
+ }
+ bcal_cipher_enc(ctx->accu, &(ctx->cctx));
+}
+
+void bcal_cmac_ctx2mac(void* dest, uint16_t length_b, const bcal_cmac_ctx_t* ctx){
+ memcpy(dest, ctx->accu, length_b/8);
+ if(length_b&7){
+ ((uint8_t*)dest)[length_b/8] &= 0xff>>(length_b&7);
+ ((uint8_t*)dest)[length_b/8] |= (0xff00>>(length_b&7))&(ctx->accu[length_b/8]);
+ }
+}
+
+void bcal_cmac(void* dest, uint16_t out_length_b, const void* block, uint32_t length_b, bcal_cmac_ctx_t* ctx){
+ uint16_t blocksize_b;
+ blocksize_b = ctx->blocksize_B*8;
+ while(length_b>blocksize_b){
+ bcal_cmac_nextBlock(ctx, block);
+ block = (uint8_t*)block + ctx->blocksize_B;
+ length_b -= blocksize_b;
+ }
+ bcal_cmac_lastBlock(ctx, block, length_b);
+ bcal_cmac_ctx2mac(dest, out_length_b, ctx);
+}
--- /dev/null
+/* bcal-cmac.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2010 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef BCALCMAC_H_
+#define BCALCMAC_H_
+
+#include <stdint.h>
+#include "bcal-basic.h"
+#include "blockcipher_descriptor.h"
+
+typedef struct{
+ bcdesc_t* desc;
+ bcgen_ctx_t cctx;
+ uint8_t* accu;
+ uint8_t* k1;
+ uint8_t* k2;
+ uint8_t* lastblock;
+ uint8_t last_set;
+ uint8_t blocksize_B;
+} bcal_cmac_ctx_t;
+
+uint8_t bcal_cmac_init(const bcdesc_t* desc, const void* key, uint16_t keysize_b, bcal_cmac_ctx_t* ctx);
+void bcal_cmac_free(bcal_cmac_ctx_t* ctx);
+void bcal_cmac_nextBlock(bcal_cmac_ctx_t* ctx, const void* block);
+void bcal_cmac_lastBlock(bcal_cmac_ctx_t* ctx, const void* block, uint16_t length_b);
+void bcal_cmac_ctx2mac(void* dest, uint16_t length_b, const bcal_cmac_ctx_t* ctx);
+void bcal_cmac(void* dest, uint16_t out_length_b, const void* block, uint32_t length_b, bcal_cmac_ctx_t* ctx);
+
+#endif /* BCALCMAC_H_ */
--- /dev/null
+/* bcal-ofb.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2010 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+#include <string.h>
+#include "bcal-ofb.h"
+#include "bcal-basic.h"
+#include "memxor.h"
+
+
+uint8_t bcal_ofb_init(const bcdesc_t* desc, const void* key, uint16_t keysize_b, bcal_ofb_ctx_t* ctx){
+ ctx->desc = (bcdesc_t*)desc;
+ ctx->blocksize_B = (bcal_cipher_getBlocksize_b(desc)+7)/8;
+ ctx->in_block=malloc(ctx->blocksize_B);
+ if(ctx->in_block==NULL){
+ return 0x11;
+ }
+ return bcal_cipher_init(desc, key, keysize_b, &(ctx->cctx));
+}
+
+void bcal_ofb_free(bcal_ofb_ctx_t* ctx){
+ free(ctx->in_block);
+ bcal_cipher_free(&(ctx->cctx));
+}
+
+void bcal_ofb_loadIV(const void* iv, bcal_ofb_ctx_t* ctx){
+ if(iv){
+ memcpy(ctx->in_block, iv, ctx->blocksize_B);
+ }
+}
+
+void bcal_ofb_encNext(void* block, bcal_ofb_ctx_t* ctx){
+ bcal_cipher_enc(ctx->in_block , &(ctx->cctx));
+ memxor(block, ctx->in_block, ctx->blocksize_B);
+}
+
+void bcal_ofb_decNext(void* block, bcal_ofb_ctx_t* ctx){
+ bcal_cipher_enc(ctx->in_block , &(ctx->cctx));
+ memxor(block, ctx->in_block, ctx->blocksize_B);
+}
+
+
+void bcal_ofb_encMsg(const void* iv, void* msg, uint32_t msg_len_b, bcal_ofb_ctx_t* ctx){
+ uint16_t block_len_b;
+ block_len_b = ctx->blocksize_B*8;
+ bcal_ofb_loadIV(iv, ctx);
+ while(msg_len_b>block_len_b){
+ bcal_ofb_encNext(msg, ctx);
+ msg_len_b -= block_len_b;
+ msg = (uint8_t*)msg + ctx->blocksize_B;
+ }
+ bcal_cipher_enc(ctx->in_block, &(ctx->cctx));
+ ctx->in_block[msg_len_b/8] = 0xff00>>(msg_len_b&7);
+ memxor(msg, ctx->in_block, (msg_len_b+7)/8);
+}
+
+void bcal_ofb_decMsg(const void* iv, void* msg, uint32_t msg_len_b, bcal_ofb_ctx_t* ctx){
+ bcal_ofb_encMsg(iv, msg, msg_len_b, ctx);
+}
+
--- /dev/null
+/* bcal-ofb.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2010 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#ifndef BCALOFB_H_
+#define BCALOFB_H_
+
+#include <stdint.h>
+#include "bcal-basic.h"
+#include "blockcipher_descriptor.h"
+
+
+typedef struct{
+ bcdesc_t* desc;
+ bcgen_ctx_t cctx;
+ uint8_t* in_block;
+ uint8_t blocksize_B;
+} bcal_ofb_ctx_t;
+
+
+uint8_t bcal_ofb_init(const bcdesc_t* desc, const void* key, uint16_t keysize_b, bcal_ofb_ctx_t* ctx);
+void bcal_ofb_free(bcal_ofb_ctx_t* ctx);
+void bcal_ofb_loadIV(const void* iv, bcal_ofb_ctx_t* ctx);
+void bcal_ofb_encNext(void* block, bcal_ofb_ctx_t* ctx);
+void bcal_ofb_decNext(void* block, bcal_ofb_ctx_t* ctx);
+void bcal_ofb_encMsg(const void* iv, void* msg, uint32_t msg_len_b, bcal_ofb_ctx_t* ctx);
+void bcal_ofb_decMsg(const void* iv, void* msg, uint32_t msg_len_b, bcal_ofb_ctx_t* ctx);
+
+
+#endif /* BCALOFB_H_ */
--- /dev/null
+/* bcal_aes128.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file bcal_aes128.c
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-08
+ * \license GPLv3 or later
+ *
+ */
+
+#include <avr/pgmspace.h>
+#include <stdlib.h>
+#include "blockcipher_descriptor.h"
+#include "aes.h"
+#include "aes128_enc.h"
+#include "aes128_dec.h"
+#include "aes_keyschedule.h"
+#include "keysize_descriptor.h"
+
+const char aes128_str[] PROGMEM = "AES-128";
+
+const uint8_t aes128_keysize_desc[] PROGMEM = { KS_TYPE_LIST, 1, KS_INT(128),
+ KS_TYPE_TERMINATOR };
+
+const bcdesc_t aes128_desc PROGMEM = {
+ BCDESC_TYPE_BLOCKCIPHER,
+ BC_INIT_TYPE_1,
+ aes128_str,
+ sizeof(aes128_ctx_t),
+ 128,
+ {(void_fpt)aes128_init},
+ {(void_fpt)aes128_enc},
+ {(void_fpt)aes128_dec},
+ (bc_free_fpt)NULL,
+ aes128_keysize_desc
+};
+
+
--- /dev/null
+/* bcal_aes128.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file bcal_aes128.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-08
+ * \license GPLv3 or later
+ *
+ */
+
+#if (defined(AVR))
+#include <avr\pgmspace.h>
+#else
+#include <pgmspace.h>
+#endif
+#include "blockcipher_descriptor.h"
+#include "aes.h"
+#include "aes128_enc.h"
+#include "aes128_dec.h"
+#include "keysize_descriptor.h"
+
+extern const bcdesc_t aes128_desc;
--- /dev/null
+/* bcal_aes128.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file bcal_aes128.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-08
+ * \license GPLv3 or later
+ *
+ */
+
+#include <avr/pgmspace.h>
+#include "blockcipher_descriptor.h"
+#include "aes.h"
+#include "aes128_enc.h"
+#include "aes128_dec.h"
+#include "keysize_descriptor.h"
+
+extern const bcdesc_t aes128_desc;
--- /dev/null
+/* bcal_aes192.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file bcal_aes192.c
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-08
+ * \license GPLv3 or later
+ *
+ */
+#if (defined(AVR))
+#include <avr\pgmspace.h>
+#else
+#include <pgmspace.h>
+#endif
+#include <stdlib.h>
+#include "blockcipher_descriptor.h"
+#include "aes.h"
+#include "aes192_enc.h"
+#include "aes192_dec.h"
+#include "aes_keyschedule.h"
+#include "keysize_descriptor.h"
+
+const char aes192_str[] PROGMEM = "AES-192";
+
+const uint8_t aes192_keysize_desc[] PROGMEM = { KS_TYPE_LIST, 1, KS_INT(192),
+ KS_TYPE_TERMINATOR };
+
+const bcdesc_t aes192_desc PROGMEM = {
+ BCDESC_TYPE_BLOCKCIPHER,
+ BC_INIT_TYPE_1,
+ aes192_str,
+ sizeof(aes192_ctx_t),
+ 128,
+ {(void_fpt)aes192_init},
+ {(void_fpt)aes192_enc},
+ {(void_fpt)aes192_dec},
+ (bc_free_fpt)NULL,
+ aes192_keysize_desc
+};
+
+
--- /dev/null
+/* bcal_aes192.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file bcal_aes192.c
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-08
+ * \license GPLv3 or later
+ *
+ */
+
+#include <avr/pgmspace.h>
+#include <stdlib.h>
+#include "blockcipher_descriptor.h"
+#include "aes.h"
+#include "aes192_enc.h"
+#include "aes192_dec.h"
+#include "aes_keyschedule.h"
+#include "keysize_descriptor.h"
+
+const char aes192_str[] PROGMEM = "AES-192";
+
+const uint8_t aes192_keysize_desc[] PROGMEM = { KS_TYPE_LIST, 1, KS_INT(192),
+ KS_TYPE_TERMINATOR };
+
+const bcdesc_t aes192_desc PROGMEM = {
+ BCDESC_TYPE_BLOCKCIPHER,
+ BC_INIT_TYPE_1,
+ aes192_str,
+ sizeof(aes192_ctx_t),
+ 128,
+ {(void_fpt)aes192_init},
+ {(void_fpt)aes192_enc},
+ {(void_fpt)aes192_dec},
+ (bc_free_fpt)NULL,
+ aes192_keysize_desc
+};
+
+
--- /dev/null
+/* bcal_aes192.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file bcal_aes192.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-08
+ * \license GPLv3 or later
+ *
+ */
+#if (defined(AVR))
+#include <avr\pgmspace.h>
+#else
+#include <pgmspace.h>
+#endif
+
+#include "blockcipher_descriptor.h"
+#include "aes.h"
+#include "aes192_enc.h"
+#include "aes192_dec.h"
+#include "keysize_descriptor.h"
+
+extern const bcdesc_t aes192_desc;
--- /dev/null
+/* bcal_aes192.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file bcal_aes192.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-08
+ * \license GPLv3 or later
+ *
+ */
+
+#include <avr/pgmspace.h>
+#include "blockcipher_descriptor.h"
+#include "aes.h"
+#include "aes192_enc.h"
+#include "aes192_dec.h"
+#include "keysize_descriptor.h"
+
+extern const bcdesc_t aes192_desc;
--- /dev/null
+/* bcal_aes256.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file bcal_aes256.c
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-08
+ * \license GPLv3 or later
+ *
+ */
+
+#include <avr/pgmspace.h>
+#include <stdlib.h>
+#include "blockcipher_descriptor.h"
+#include "aes.h"
+#include "aes256_enc.h"
+#include "aes256_dec.h"
+#include "aes_keyschedule.h"
+#include "keysize_descriptor.h"
+
+const char aes256_str[] PROGMEM = "AES-256";
+
+const uint8_t aes256_keysize_desc[] PROGMEM = { KS_TYPE_LIST, 1, KS_INT(256),
+ KS_TYPE_TERMINATOR };
+
+const bcdesc_t aes256_desc PROGMEM = {
+ BCDESC_TYPE_BLOCKCIPHER,
+ BC_INIT_TYPE_1,
+ aes256_str,
+ sizeof(aes256_ctx_t),
+ 128,
+ {(void_fpt)aes256_init},
+ {(void_fpt)aes256_enc},
+ {(void_fpt)aes256_dec},
+ (bc_free_fpt)NULL,
+ aes256_keysize_desc
+};
+
+
--- /dev/null
+/* bcal_aes256.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file bcal_aes256.h
+ * \email daniel.otte@rub.de
+ * \author Daniel Otte
+ * \date 2009-01-08
+ * \license GPLv3 or later
+ *
+ */
+
+#include <avr/pgmspace.h>
+#include "blockcipher_descriptor.h"
+#include "aes.h"
+#include "aes256_enc.h"
+#include "aes256_dec.h"
+#include "keysize_descriptor.h"
+
+extern const bcdesc_t aes256_desc;
--- /dev/null
+/* blockcipher_descriptor.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file blockcipher_descriptor.h
+ * \author Daniel Otte
+ * \date 2009-02-04
+ *
+ * \license GPLv3 or later
+ *
+ */
+
+#ifndef BLOCKCIPHER_DESCRIPTOR_H_
+#define BLOCKCIPHER_DESCRIPTOR_H_
+#include <stdint.h>
+#if (defined(AVR))
+#include <avr\pgmspace.h>
+#else
+#include <pgmspace.h>
+#endif
+
+#ifndef VOID_FPT
+#define VOID_FPT
+typedef void(*void_fpt)(void);
+#endif
+
+typedef void(*bc_init1_fpt)(void*, void*);
+typedef void(*bc_init2_fpt)(void*, uint16_t,void*);
+typedef void(*bc_enc1_fpt)(void*, void*);
+typedef void(*bc_enc2_fpt)(void*, void*, void*);
+typedef void(*bc_dec1_fpt)(void*, void*);
+typedef void(*bc_dec2_fpt)(void*, void*, void*);
+typedef void(*bc_free_fpt)(void*);
+
+typedef union{
+ void_fpt initvoid;
+ bc_init1_fpt init1;
+ bc_init2_fpt init2;
+} bc_init_fpt;
+
+typedef union{
+ void_fpt encvoid;
+ bc_enc1_fpt enc1;
+ bc_enc2_fpt enc2;
+} bc_enc_fpt;
+
+typedef union{
+ void_fpt decvoid;
+ bc_dec1_fpt dec1;
+ bc_dec2_fpt dec2;
+} bc_dec_fpt;
+
+#define BC_INIT_TYPE 0x01
+#define BC_INIT_TYPE_1 0x00 /* for fix keylength */
+#define BC_INIT_TYPE_2 0x01 /* keylength is passed as second parameter */
+
+#define BC_ENC_TYPE 0x02
+#define BC_ENC_TYPE_1 0x00
+#define BC_ENC_TYPE_2 0x02
+#
+#define BC_DEC_TYPE 0x04
+#define BC_DEC_TYPE_1 0x00
+#define BC_DEC_TYPE_2 0x04
+
+#define BCDESC_TYPE_BLOCKCIPHER 0x01
+
+typedef struct {
+ uint8_t type; /* 1==blockcipher */
+ uint8_t flags;
+ PGM_P name;
+ uint16_t ctxsize_B;
+ uint16_t blocksize_b;
+ bc_init_fpt init;
+ bc_enc_fpt enc;
+ bc_dec_fpt dec;
+ bc_free_fpt free;
+ PGM_VOID_P valid_keysize_desc;
+} bcdesc_t; /* blockcipher descriptor type */
+
+typedef struct{
+ bcdesc_t* desc_ptr;
+ uint16_t keysize;
+ void* ctx;
+} bcgen_ctx_t;
+
+#endif /* BLOCKCIPHER_DESCRIPTOR_H_ */
+
--- /dev/null
+/* blockcipher_descriptor.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file blockcipher_descriptor.h
+ * \author Daniel Otte
+ * \date 2009-02-04
+ *
+ * \license GPLv3 or later
+ *
+ */
+
+#ifndef BLOCKCIPHER_DESCRIPTOR_H_
+#define BLOCKCIPHER_DESCRIPTOR_H_
+#include <stdint.h>
+#include <avr/pgmspace.h>
+
+
+#ifndef VOID_FPT
+#define VOID_FPT
+typedef void(*void_fpt)(void);
+#endif
+
+typedef void(*bc_init1_fpt)(void*, void*);
+typedef void(*bc_init2_fpt)(void*, uint16_t,void*);
+typedef void(*bc_enc1_fpt)(void*, void*);
+typedef void(*bc_enc2_fpt)(void*, void*, void*);
+typedef void(*bc_dec1_fpt)(void*, void*);
+typedef void(*bc_dec2_fpt)(void*, void*, void*);
+typedef void(*bc_free_fpt)(void*);
+
+typedef union{
+ void_fpt initvoid;
+ bc_init1_fpt init1;
+ bc_init2_fpt init2;
+} bc_init_fpt;
+
+typedef union{
+ void_fpt encvoid;
+ bc_enc1_fpt enc1;
+ bc_enc2_fpt enc2;
+} bc_enc_fpt;
+
+typedef union{
+ void_fpt decvoid;
+ bc_dec1_fpt dec1;
+ bc_dec2_fpt dec2;
+} bc_dec_fpt;
+
+#define BC_INIT_TYPE 0x01
+#define BC_INIT_TYPE_1 0x00 /* for fix keylength */
+#define BC_INIT_TYPE_2 0x01 /* keylength is passed as second parameter */
+
+#define BC_ENC_TYPE 0x02
+#define BC_ENC_TYPE_1 0x00
+#define BC_ENC_TYPE_2 0x02
+#
+#define BC_DEC_TYPE 0x04
+#define BC_DEC_TYPE_1 0x00
+#define BC_DEC_TYPE_2 0x04
+
+#define BCDESC_TYPE_BLOCKCIPHER 0x01
+
+typedef struct {
+ uint8_t type; /* 1==blockcipher */
+ uint8_t flags;
+ PGM_P name;
+ uint16_t ctxsize_B;
+ uint16_t blocksize_b;
+ bc_init_fpt init;
+ bc_enc_fpt enc;
+ bc_dec_fpt dec;
+ bc_free_fpt free;
+ PGM_VOID_P valid_keysize_desc;
+} bcdesc_t; /* blockcipher descriptor type */
+
+typedef struct{
+ bcdesc_t* desc_ptr;
+ uint16_t keysize;
+ void* ctx;
+} bcgen_ctx_t;
+
+#endif /* BLOCKCIPHER_DESCRIPTOR_H_ */
+
--- /dev/null
+/* gf256mul.S */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * File: gf256mul.S
+ * Author: Daniel Otte
+ * Date: 2008-12-19
+ * License: GPLv3 or later
+ * Description: peasant's algorithm for multiplication in GF(2^8)
+ *
+ */
+
+#include <avr/io.h>
+#define OPTIMIZE_SMALL_A
+
+/*
+ * param a: r24
+ * param b: r22
+ * param reducer: r20
+ */
+A = 23
+B = 22
+P = 24
+.global gf256mul
+
+#ifdef OPTIMIZE_SMALL_A
+gf256mul:
+ mov A, r24
+ clr r24
+1:
+ lsr A
+ breq 4f
+ brcc 2f
+ eor P, B
+2:
+ lsl B
+ brcc 3f
+ eor B, r20
+3:
+ rjmp 1b
+4:
+ brcc 2f
+ eor P, B
+2:
+ ret
+
+#else
+
+gf256mul:
+ mov r21, r24
+ clr r24
+ ldi r25, 8
+1:
+ lsr A
+ brcc 2f
+ eor P, B
+2:
+ lsl B
+ brcc 3f
+ eor B, r20
+3:
+ dec r25
+ brne 1b
+ ret
+
+#endif
--- /dev/null
+/* gf256mul.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef GF256MUL_H_
+#define GF256MUL_H_
+
+/**
+ * \author Daniel Otte
+ * \email daniel.otte@rub.de
+ * \date 2008-12-19
+ * \license GPLv3
+ * \brief
+ *
+ *
+ */
+
+#include <stdint.h>
+
+uint8_t gf256mul(uint8_t a, uint8_t b, uint8_t reducer);
+
+#endif /* GF256MUL_H_ */
+
--- /dev/null
+/* keysize_descriptor.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file keysize_descriptor.c
+ * \author Daniel Otte
+ * \email daniel.otte@rub.de
+ * \date 2009-01-07
+ * \license GPLv3 or later
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#if (defined(__AVR__))
+#include <avr/pgmspace.h>
+ #else
+#include <pgmspace.h>
+#endif
+
+
+#include "keysize_descriptor.h"
+
+uint8_t is_valid_keysize_P(PGM_VOID_P ks_desc, uint16_t keysize){
+ uint8_t type;
+ type = pgm_read_byte(ks_desc++);
+ if(type==KS_TYPE_TERMINATOR)
+ return 0;
+ if(type==KS_TYPE_LIST){
+ uint8_t items;
+ uint16_t item;
+ items = pgm_read_byte(ks_desc++);
+ while(items--){
+ item = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ if(item==keysize)
+ return 1;
+ }
+ ks_desc = (uint8_t*)ks_desc - 2;
+ }
+ if(type==KS_TYPE_RANGE){
+ uint16_t max, min;
+ min = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ max = pgm_read_word(ks_desc);
+ if(min<=keysize && keysize<=max)
+ return 1;
+ }
+ if(type==KS_TYPE_ARG_RANGE){
+ uint16_t max, min, dist, offset;
+ min = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ max = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ dist = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ offset = pgm_read_word(ks_desc);
+ if(min<=keysize && keysize<=max && (keysize%dist==offset))
+ return 1;
+ }
+ if(type>KS_TYPE_ARG_RANGE){
+ /* bad error, you may insert a big warning message here */
+ return 0;
+ }
+ return is_valid_keysize_P((uint8_t*)ks_desc+1, keysize); /* search the next record */
+}
+
+uint16_t get_keysize(PGM_VOID_P ks_desc){
+ uint8_t type;
+ uint16_t keysize;
+ type = pgm_read_byte(ks_desc);
+ if(type==KS_TYPE_LIST){
+ ks_desc = (uint8_t*)ks_desc + 1;
+ }
+ ks_desc = (uint8_t*)ks_desc + 1;
+ keysize = pgm_read_word(ks_desc);
+ return keysize;
+}
+
+uint16_t get_keysizes(PGM_VOID_P ks_desc, uint16_t** list){
+ uint8_t type;
+ uint16_t items;
+ uint8_t i;
+ type = pgm_read_byte(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 1;
+ if(type==KS_TYPE_LIST){
+ items = pgm_read_byte(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 1;
+ if(!*list){
+ *list = malloc(items*2);
+ if(!*list){
+ return 0;
+ }
+ }
+ for(i=0; i<items; ++i){
+ ((uint16_t*)(*list))[i] = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ }
+ return items;
+ }
+ if(type==KS_TYPE_ARG_RANGE){
+ uint16_t min, max, distance, offset;
+ min = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ max = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ distance = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ offset = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ items = (max-min)/distance+1;
+ if(min%distance!=offset){
+ --items;
+ min += (distance-(min%distance-offset))%distance;
+ }
+ if(!*list){
+ *list = malloc(items*2);
+ if(!*list){
+ return 0;
+ }
+ }
+ i=0;
+ while(min<max){
+ ((uint16_t*)*list)[i++] = min;
+ min += distance;
+ }
+ return i;
+ }
+ if(type==KS_TYPE_RANGE){
+ uint16_t min, max, distance=8, offset=0;
+ min = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ max = pgm_read_word(ks_desc);
+ items = (max-min)/distance+1;
+ if(min%distance!=offset){
+ --items;
+ min += (distance-(min%distance-offset))%distance;
+ }
+ if(!*list){
+ *list = malloc(items*2);
+ if(!*list){
+ return 0;
+ }
+ }
+ i=0;
+ while(min<max){
+ ((uint16_t*)*list)[i++] = min;
+ min += distance;
+ }
+ return i;
+ }
+ return 0;
+}
--- /dev/null
+/* keysize_descriptor.c */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file keysize_descriptor.c
+ * \author Daniel Otte
+ * \email daniel.otte@rub.de
+ * \date 2009-01-07
+ * \license GPLv3 or later
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <avr/pgmspace.h>
+#include "keysize_descriptor.h"
+
+uint8_t is_valid_keysize_P(PGM_VOID_P ks_desc, uint16_t keysize){
+ uint8_t type;
+ type = pgm_read_byte(ks_desc++);
+ if(type==KS_TYPE_TERMINATOR)
+ return 0;
+ if(type==KS_TYPE_LIST){
+ uint8_t items;
+ uint16_t item;
+ items = pgm_read_byte(ks_desc++);
+ while(items--){
+ item = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ if(item==keysize)
+ return 1;
+ }
+ ks_desc = (uint8_t*)ks_desc - 2;
+ }
+ if(type==KS_TYPE_RANGE){
+ uint16_t max, min;
+ min = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ max = pgm_read_word(ks_desc);
+ if(min<=keysize && keysize<=max)
+ return 1;
+ }
+ if(type==KS_TYPE_ARG_RANGE){
+ uint16_t max, min, dist, offset;
+ min = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ max = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ dist = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ offset = pgm_read_word(ks_desc);
+ if(min<=keysize && keysize<=max && (keysize%dist==offset))
+ return 1;
+ }
+ if(type>KS_TYPE_ARG_RANGE){
+ /* bad error, you may insert a big warning message here */
+ return 0;
+ }
+ return is_valid_keysize_P((uint8_t*)ks_desc+1, keysize); /* search the next record */
+}
+
+uint16_t get_keysize(PGM_VOID_P ks_desc){
+ uint8_t type;
+ uint16_t keysize;
+ type = pgm_read_byte(ks_desc);
+ if(type==KS_TYPE_LIST){
+ ks_desc = (uint8_t*)ks_desc + 1;
+ }
+ ks_desc = (uint8_t*)ks_desc + 1;
+ keysize = pgm_read_word(ks_desc);
+ return keysize;
+}
+
+uint16_t get_keysizes(PGM_VOID_P ks_desc, uint16_t** list){
+ uint8_t type;
+ uint16_t items;
+ uint8_t i;
+ type = pgm_read_byte(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 1;
+ if(type==KS_TYPE_LIST){
+ items = pgm_read_byte(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 1;
+ if(!*list){
+ *list = malloc(items*2);
+ if(!*list){
+ return 0;
+ }
+ }
+ for(i=0; i<items; ++i){
+ ((uint16_t*)(*list))[i] = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ }
+ return items;
+ }
+ if(type==KS_TYPE_ARG_RANGE){
+ uint16_t min, max, distance, offset;
+ min = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ max = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ distance = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ offset = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ items = (max-min)/distance+1;
+ if(min%distance!=offset){
+ --items;
+ min += (distance-(min%distance-offset))%distance;
+ }
+ if(!*list){
+ *list = malloc(items*2);
+ if(!*list){
+ return 0;
+ }
+ }
+ i=0;
+ while(min<max){
+ ((uint16_t*)*list)[i++] = min;
+ min += distance;
+ }
+ return i;
+ }
+ if(type==KS_TYPE_RANGE){
+ uint16_t min, max, distance=8, offset=0;
+ min = pgm_read_word(ks_desc);
+ ks_desc = (uint8_t*)ks_desc + 2;
+ max = pgm_read_word(ks_desc);
+ items = (max-min)/distance+1;
+ if(min%distance!=offset){
+ --items;
+ min += (distance-(min%distance-offset))%distance;
+ }
+ if(!*list){
+ *list = malloc(items*2);
+ if(!*list){
+ return 0;
+ }
+ }
+ i=0;
+ while(min<max){
+ ((uint16_t*)*list)[i++] = min;
+ min += distance;
+ }
+ return i;
+ }
+ return 0;
+}
--- /dev/null
+/* keysize_descriptor.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file keysize_descriptor.h
+ * \author Daniel Otte
+ * \email daniel.otte@rub.de
+ * \date 2009-01-07
+ * \license GPLv3 or later
+ */
+
+#ifndef KEYSIZE_DESCRIPTOR_H_
+#define KEYSIZE_DESCRIPTOR_H_
+
+#include <stdint.h>
+#if (defined(__AVR__))
+#include <avr/pgmspace.h>
+ #else
+#include <pgmspace.h>
+#endif
+
+#define KS_TYPE_TERMINATOR 0x00
+#define KS_TYPE_LIST 0x01
+#define KS_TYPE_RANGE 0x02
+#define KS_TYPE_ARG_RANGE 0x03
+
+#define KS_INT(a) ((a)&0xFF), ((a)>>8)
+
+typedef struct{ /* keysize is valid if listed in items */
+ uint8_t n_items; /* number of items (value 0 is reserved) */
+ uint16_t items[]; /* list of valid lengths */
+}keysize_desc_list_t;
+
+typedef struct{ /* keysize is valid if min<=keysize<=max */
+ uint16_t min;
+ uint16_t max;
+}keysize_desc_range_t;
+
+typedef struct{ /* keysize is valid if min<=keysize<=max and if keysize mod distance == offset */
+ uint16_t min;
+ uint16_t max;
+ uint16_t distance;
+ uint16_t offset;
+}keysize_desc_arg_range_t;
+
+uint8_t is_valid_keysize_P(PGM_VOID_P ks_desc, uint16_t keysize);
+uint16_t get_keysize(PGM_VOID_P ks_desc);
+uint16_t get_keysizes(PGM_VOID_P ks_desc, uint16_t** list);
+
+
+#endif /* KEYSIZE_DESCRIPTOR_H_ */
--- /dev/null
+/* keysize_descriptor.h */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2009 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * \file keysize_descriptor.h
+ * \author Daniel Otte
+ * \email daniel.otte@rub.de
+ * \date 2009-01-07
+ * \license GPLv3 or later
+ */
+
+#ifndef KEYSIZE_DESCRIPTOR_H_
+#define KEYSIZE_DESCRIPTOR_H_
+
+#include <stdint.h>
+#include <avr/pgmspace.h>
+
+#define KS_TYPE_TERMINATOR 0x00
+#define KS_TYPE_LIST 0x01
+#define KS_TYPE_RANGE 0x02
+#define KS_TYPE_ARG_RANGE 0x03
+
+#define KS_INT(a) ((a)&0xFF), ((a)>>8)
+
+typedef struct{ /* keysize is valid if listed in items */
+ uint8_t n_items; /* number of items (value 0 is reserved) */
+ uint16_t items[]; /* list of valid lengths */
+}keysize_desc_list_t;
+
+typedef struct{ /* keysize is valid if min<=keysize<=max */
+ uint16_t min;
+ uint16_t max;
+}keysize_desc_range_t;
+
+typedef struct{ /* keysize is valid if min<=keysize<=max and if keysize mod distance == offset */
+ uint16_t min;
+ uint16_t max;
+ uint16_t distance;
+ uint16_t offset;
+}keysize_desc_arg_range_t;
+
+uint8_t is_valid_keysize_P(PGM_VOID_P ks_desc, uint16_t keysize);
+uint16_t get_keysize(PGM_VOID_P ks_desc);
+uint16_t get_keysizes(PGM_VOID_P ks_desc, uint16_t** list);
+
+
+#endif /* KEYSIZE_DESCRIPTOR_H_ */
--- /dev/null
+{
+ "name": "AESLib",
+ "keywords": "cryptography, aes",
+ "description": "Small AES implementation in ASM",
+ "repository":
+ {
+ "type": "git",
+ "url": "https://github.com/DavyLandman/AESLib.git"
+ },
+ "frameworks": "arduino",
+ "platforms": "atmelavr"
+}
--- /dev/null
+/* memxor.S */
+/*
+ This file is part of the AVR-Crypto-Lib.
+ Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * File: memxor.S
+ * Author: Daniel Otte
+ * Date: 2008-08-07
+ * License: GPLv3 or later
+ * Description: memxor, XORing one block into another
+ *
+ */
+
+/*
+ * void memxor(void* dest, const void* src, uint16_t n);
+ */
+ /*
+ * param dest is passed in r24:r25
+ * param src is passed in r22:r23
+ * param n is passed in r20:r21
+ */
+.global memxor
+memxor:
+ movw r30, r24
+ movw r26, r22
+ movw r24, r20
+ adiw r24, 0
+ breq 2f
+1:
+ ld r20, X+
+ ld r21, Z
+ eor r20, r21
+ st Z+, r20
+ sbiw r24, 1
+ brne 1b
+2:
+ ret
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+#ifndef MEMXOR_H_
+#define MEMXOR_H_
+#include <stdint.h>
+
+void memxor(void* dest, const void* src, uint16_t n);
+void memxor_P(void* dest, const void* src, uint16_t n);
+
+
+#endif
--- /dev/null
+/*
+ Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+ */
+ /* Galileo support from spaniakos <spaniakos@gmail.com> */
+
+/**
+ * @file printf.h
+ *
+ * Setup necessary to direct stdout to the Arduino Serial library, which
+ * enables 'printf'
+ */
+
+#ifndef __PRINTF_H__
+#define __PRINTF_H__
+
+#if defined (ARDUINO) && !defined (__arm__) && !defined(__ARDUINO_X86__)
+
+int serial_putc( char c, FILE * )
+{
+ Serial.write( c );
+
+ return c;
+}
+
+void printf_begin(void)
+{
+ fdevopen( &serial_putc, 0 );
+}
+
+#elif defined (__arm__)
+
+void printf_begin(void){}
+
+#elif defined(__ARDUINO_X86__)
+int serial_putc( char c, FILE * )
+{
+ Serial.write( c );
+
+ return c;
+}
+
+void printf_begin(void)
+{
+ //JESUS - For reddirect stdout to /dev/ttyGS0 (Serial Monitor port)
+ stdout = freopen("/dev/ttyGS0","w",stdout);
+ delay(500);
+ printf("redirecting to Serial...");
+
+ //JESUS -----------------------------------------------------------
+}
+#else
+#error This example is only for use on Arduino.
+#endif // ARDUINO
+
+#endif // __PRINTF_H__
--- /dev/null
+/**
+ * An extremely minimal crypto library for Arduino devices.
+ *
+ * The SHA256 and AES implementations are derived from axTLS
+ * (http://axtls.sourceforge.net/), Copyright (c) 2008, Cameron Rich.
+ *
+ * Ported and refactored by Chris Ellis 2016.
+ *
+ */
+
+#include <Crypto.h>
+
+/**
+ * Byte order helpers
+ */
+
+
+//#if BYTE_ORDER == BIG_ENDIAN
+/*
+inline static uint16_t crypto_htons(uint16_t x)
+{
+ return x;
+}
+
+inline static uint16_t crypto_ntohs(uint16_t x)
+{
+ return x;
+}
+
+inline static uint32_t crypto_htonl(uint32_t x)
+{
+ return x;
+}
+
+inline static uint32_t crypto_ntohl(uint32_t x)
+{
+ return x;
+}
+*/
+//#else
+
+inline static uint16_t crypto_htons(uint16_t x)
+{
+ return (
+ ((x & 0xff) << 8) |
+ ((x & 0xff00) >> 8)
+ );
+}
+
+inline static uint16_t crypto_ntohs(uint16_t x)
+{
+ return (
+ ((x & 0xff) << 8) |
+ ((x & 0xff00) >> 8)
+ );
+}
+
+inline static uint32_t crypto_htonl(uint32_t x)
+{
+ return (
+ ((x & 0xff) << 24) |
+ ((x & 0xff00) << 8) |
+ ((x & 0xff0000UL) >> 8) |
+ ((x & 0xff000000UL) >> 24)
+ );
+}
+
+inline static uint32_t crypto_ntohl(uint32_t x)
+{
+ return (
+ ((x & 0xff) << 24) |
+ ((x & 0xff00) << 8) |
+ ((x & 0xff0000UL) >> 8) |
+ ((x & 0xff000000UL) >> 24)
+ );
+}
+
+//#endif
+
+#define GET_UINT32(n,b,i) \
+{ \
+ (n) = ((uint32_t) (b)[(i) ] << 24) \
+ | ((uint32_t) (b)[(i) + 1] << 16) \
+ | ((uint32_t) (b)[(i) + 2] << 8) \
+ | ((uint32_t) (b)[(i) + 3] ); \
+}
+
+#define PUT_UINT32(n,b,i) \
+{ \
+ (b)[(i) ] = (byte) ((n) >> 24); \
+ (b)[(i) + 1] = (byte) ((n) >> 16); \
+ (b)[(i) + 2] = (byte) ((n) >> 8); \
+ (b)[(i) + 3] = (byte) ((n) ); \
+}
+
+static const byte sha256_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/**
+ * Initialize the SHA256 hash
+ */
+SHA256::SHA256()
+{
+ total[0] = 0;
+ total[1] = 0;
+ state[0] = 0x6A09E667;
+ state[1] = 0xBB67AE85;
+ state[2] = 0x3C6EF372;
+ state[3] = 0xA54FF53A;
+ state[4] = 0x510E527F;
+ state[5] = 0x9B05688C;
+ state[6] = 0x1F83D9AB;
+ state[7] = 0x5BE0CD19;
+}
+
+void SHA256::SHA256_Process(const byte digest[64])
+{
+ uint32_t temp1, temp2, W[64];
+ uint32_t A, B, C, D, E, F, G, H;
+
+ GET_UINT32(W[0], digest, 0);
+ GET_UINT32(W[1], digest, 4);
+ GET_UINT32(W[2], digest, 8);
+ GET_UINT32(W[3], digest, 12);
+ GET_UINT32(W[4], digest, 16);
+ GET_UINT32(W[5], digest, 20);
+ GET_UINT32(W[6], digest, 24);
+ GET_UINT32(W[7], digest, 28);
+ GET_UINT32(W[8], digest, 32);
+ GET_UINT32(W[9], digest, 36);
+ GET_UINT32(W[10], digest, 40);
+ GET_UINT32(W[11], digest, 44);
+ GET_UINT32(W[12], digest, 48);
+ GET_UINT32(W[13], digest, 52);
+ GET_UINT32(W[14], digest, 56);
+ GET_UINT32(W[15], digest, 60);
+
+#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
+#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
+
+#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
+#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
+
+#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
+#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
+
+#define F0(x,y,z) ((x & y) | (z & (x | y)))
+#define F1(x,y,z) (z ^ (x & (y ^ z)))
+
+#define R(t) \
+( \
+ W[t] = S1(W[t - 2]) + W[t - 7] + \
+ S0(W[t - 15]) + W[t - 16] \
+)
+
+#define P(a,b,c,d,e,f,g,h,x,K) \
+{ \
+ temp1 = h + S3(e) + F1(e,f,g) + K + x; \
+ temp2 = S2(a) + F0(a,b,c); \
+ d += temp1; h = temp1 + temp2; \
+}
+
+ A = state[0];
+ B = state[1];
+ C = state[2];
+ D = state[3];
+ E = state[4];
+ F = state[5];
+ G = state[6];
+ H = state[7];
+
+ P(A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98);
+ P(H, A, B, C, D, E, F, G, W[ 1], 0x71374491);
+ P(G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF);
+ P(F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5);
+ P(E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B);
+ P(D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1);
+ P(C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4);
+ P(B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5);
+ P(A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98);
+ P(H, A, B, C, D, E, F, G, W[ 9], 0x12835B01);
+ P(G, H, A, B, C, D, E, F, W[10], 0x243185BE);
+ P(F, G, H, A, B, C, D, E, W[11], 0x550C7DC3);
+ P(E, F, G, H, A, B, C, D, W[12], 0x72BE5D74);
+ P(D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE);
+ P(C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7);
+ P(B, C, D, E, F, G, H, A, W[15], 0xC19BF174);
+ P(A, B, C, D, E, F, G, H, R(16), 0xE49B69C1);
+ P(H, A, B, C, D, E, F, G, R(17), 0xEFBE4786);
+ P(G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6);
+ P(F, G, H, A, B, C, D, E, R(19), 0x240CA1CC);
+ P(E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F);
+ P(D, E, F, G, H, A, B, C, R(21), 0x4A7484AA);
+ P(C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC);
+ P(B, C, D, E, F, G, H, A, R(23), 0x76F988DA);
+ P(A, B, C, D, E, F, G, H, R(24), 0x983E5152);
+ P(H, A, B, C, D, E, F, G, R(25), 0xA831C66D);
+ P(G, H, A, B, C, D, E, F, R(26), 0xB00327C8);
+ P(F, G, H, A, B, C, D, E, R(27), 0xBF597FC7);
+ P(E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3);
+ P(D, E, F, G, H, A, B, C, R(29), 0xD5A79147);
+ P(C, D, E, F, G, H, A, B, R(30), 0x06CA6351);
+ P(B, C, D, E, F, G, H, A, R(31), 0x14292967);
+ P(A, B, C, D, E, F, G, H, R(32), 0x27B70A85);
+ P(H, A, B, C, D, E, F, G, R(33), 0x2E1B2138);
+ P(G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC);
+ P(F, G, H, A, B, C, D, E, R(35), 0x53380D13);
+ P(E, F, G, H, A, B, C, D, R(36), 0x650A7354);
+ P(D, E, F, G, H, A, B, C, R(37), 0x766A0ABB);
+ P(C, D, E, F, G, H, A, B, R(38), 0x81C2C92E);
+ P(B, C, D, E, F, G, H, A, R(39), 0x92722C85);
+ P(A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1);
+ P(H, A, B, C, D, E, F, G, R(41), 0xA81A664B);
+ P(G, H, A, B, C, D, E, F, R(42), 0xC24B8B70);
+ P(F, G, H, A, B, C, D, E, R(43), 0xC76C51A3);
+ P(E, F, G, H, A, B, C, D, R(44), 0xD192E819);
+ P(D, E, F, G, H, A, B, C, R(45), 0xD6990624);
+ P(C, D, E, F, G, H, A, B, R(46), 0xF40E3585);
+ P(B, C, D, E, F, G, H, A, R(47), 0x106AA070);
+ P(A, B, C, D, E, F, G, H, R(48), 0x19A4C116);
+ P(H, A, B, C, D, E, F, G, R(49), 0x1E376C08);
+ P(G, H, A, B, C, D, E, F, R(50), 0x2748774C);
+ P(F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5);
+ P(E, F, G, H, A, B, C, D, R(52), 0x391C0CB3);
+ P(D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A);
+ P(C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F);
+ P(B, C, D, E, F, G, H, A, R(55), 0x682E6FF3);
+ P(A, B, C, D, E, F, G, H, R(56), 0x748F82EE);
+ P(H, A, B, C, D, E, F, G, R(57), 0x78A5636F);
+ P(G, H, A, B, C, D, E, F, R(58), 0x84C87814);
+ P(F, G, H, A, B, C, D, E, R(59), 0x8CC70208);
+ P(E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA);
+ P(D, E, F, G, H, A, B, C, R(61), 0xA4506CEB);
+ P(C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7);
+ P(B, C, D, E, F, G, H, A, R(63), 0xC67178F2);
+
+ state[0] += A;
+ state[1] += B;
+ state[2] += C;
+ state[3] += D;
+ state[4] += E;
+ state[5] += F;
+ state[6] += G;
+ state[7] += H;
+}
+
+/**
+ * Accepts an array of octets as the next portion of the message.
+ */
+void SHA256::doUpdate(const byte * msg, int len)
+{
+ uint32_t left = total[0] & 0x3F;
+ uint32_t fill = 64 - left;
+
+ total[0] += len;
+ total[0] &= 0xFFFFFFFF;
+
+ if (total[0] < len)
+ total[1]++;
+
+ if (left && len >= fill)
+ {
+ memcpy((void *) (buffer + left), (void *) msg, fill);
+ SHA256::SHA256_Process(buffer);
+ len -= fill;
+ msg += fill;
+ left = 0;
+ }
+
+ while (len >= 64)
+ {
+ SHA256::SHA256_Process(msg);
+ len -= 64;
+ msg += 64;
+ }
+
+ if (len)
+ {
+ memcpy((void *) (buffer + left), (void *) msg, len);
+ }
+}
+
+/**
+ * Return the 256-bit message digest into the user's array
+ */
+void SHA256::doFinal(byte *digest)
+{
+ uint32_t last, padn;
+ uint32_t high, low;
+ byte msglen[8];
+
+ high = (total[0] >> 29)
+ | (total[1] << 3);
+ low = (total[0] << 3);
+
+ PUT_UINT32(high, msglen, 0);
+ PUT_UINT32(low, msglen, 4);
+
+ last = total[0] & 0x3F;
+ padn = (last < 56) ? (56 - last) : (120 - last);
+
+ SHA256::doUpdate(sha256_padding, padn);
+ SHA256::doUpdate(msglen, 8);
+
+ PUT_UINT32(state[0], digest, 0);
+ PUT_UINT32(state[1], digest, 4);
+ PUT_UINT32(state[2], digest, 8);
+ PUT_UINT32(state[3], digest, 12);
+ PUT_UINT32(state[4], digest, 16);
+ PUT_UINT32(state[5], digest, 20);
+ PUT_UINT32(state[6], digest, 24);
+ PUT_UINT32(state[7], digest, 28);
+}
+
+bool SHA256::matches(const byte *expected)
+{
+ byte theDigest[SHA256_SIZE];
+ doFinal(theDigest);
+ for (byte i = 0; i < SHA256_SIZE; i++)
+ {
+ if (expected[i] != theDigest[i])
+ return false;
+ }
+ return true;
+}
+
+/******************************************************************************/
+
+#define rot1(x) (((x) << 24) | ((x) >> 8))
+#define rot2(x) (((x) << 16) | ((x) >> 16))
+#define rot3(x) (((x) << 8) | ((x) >> 24))
+
+/*
+ * This cute trick does 4 'mul by two' at once. Stolen from
+ * Dr B. R. Gladman <brg@gladman.uk.net> but I'm sure the u-(u>>7) is
+ * a standard graphics trick
+ * The key to this is that we need to xor with 0x1b if the top bit is set.
+ * a 1xxx xxxx 0xxx 0xxx First we mask the 7bit,
+ * b 1000 0000 0000 0000 then we shift right by 7 putting the 7bit in 0bit,
+ * c 0000 0001 0000 0000 we then subtract (c) from (b)
+ * d 0111 1111 0000 0000 and now we and with our mask
+ * e 0001 1011 0000 0000
+ */
+#define mt 0x80808080
+#define ml 0x7f7f7f7f
+#define mh 0xfefefefe
+#define mm 0x1b1b1b1b
+#define mul2(x,t) ((t)=((x)&mt), \
+ ((((x)+(x))&mh)^(((t)-((t)>>7))&mm)))
+
+#define inv_mix_col(x,f2,f4,f8,f9) (\
+ (f2)=mul2(x,f2), \
+ (f4)=mul2(f2,f4), \
+ (f8)=mul2(f4,f8), \
+ (f9)=(x)^(f8), \
+ (f8)=((f2)^(f4)^(f8)), \
+ (f2)^=(f9), \
+ (f4)^=(f9), \
+ (f8)^=rot3(f2), \
+ (f8)^=rot2(f4), \
+ (f8)^rot1(f9))
+
+/*
+ * AES S-box
+ */
+static const uint8_t aes_sbox[256] =
+{
+ 0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,
+ 0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76,
+ 0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0,
+ 0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0,
+ 0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC,
+ 0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15,
+ 0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,
+ 0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75,
+ 0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,
+ 0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84,
+ 0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,
+ 0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF,
+ 0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,
+ 0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8,
+ 0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,
+ 0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2,
+ 0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,
+ 0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73,
+ 0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,
+ 0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB,
+ 0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,
+ 0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79,
+ 0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,
+ 0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08,
+ 0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,
+ 0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A,
+ 0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,
+ 0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E,
+ 0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,
+ 0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF,
+ 0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,
+ 0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16,
+};
+
+/*
+ * AES is-box
+ */
+static const uint8_t aes_isbox[256] =
+{
+ 0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,
+ 0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,
+ 0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,
+ 0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb,
+ 0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,
+ 0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e,
+ 0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,
+ 0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25,
+ 0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,
+ 0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92,
+ 0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,
+ 0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84,
+ 0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,
+ 0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06,
+ 0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,
+ 0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b,
+ 0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,
+ 0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73,
+ 0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,
+ 0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e,
+ 0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,
+ 0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b,
+ 0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,
+ 0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4,
+ 0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,
+ 0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f,
+ 0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,
+ 0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef,
+ 0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,
+ 0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61,
+ 0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,
+ 0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
+};
+
+static const unsigned char Rcon[30]=
+{
+ 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,
+ 0x1b,0x36,0x6c,0xd8,0xab,0x4d,0x9a,0x2f,
+ 0x5e,0xbc,0x63,0xc6,0x97,0x35,0x6a,0xd4,
+ 0xb3,0x7d,0xfa,0xef,0xc5,0x91,
+};
+
+/* Perform doubling in Galois Field GF(2^8) using the irreducible polynomial
+ x^8+x^4+x^3+x+1 */
+static unsigned char AES_xtime(uint32_t x)
+{
+ return (x&0x80) ? (x<<1)^0x1b : x<<1;
+}
+
+
+/**
+ * Encrypt a single block (16 bytes) of data
+ */
+void AES::encrypt(uint32_t *data)
+{
+ /* To make this code smaller, generate the sbox entries on the fly.
+ * This will have a really heavy effect upon performance.
+ */
+ uint32_t tmp[4];
+ uint32_t tmp1, old_a0, a0, a1, a2, a3, row;
+ int curr_rnd;
+ int rounds = _rounds;
+ const uint32_t *k = _ks;
+
+ /* Pre-round key addition */
+ for (row = 0; row < 4; row++)
+ data[row] ^= *(k++);
+
+ /* Encrypt one block. */
+ for (curr_rnd = 0; curr_rnd < rounds; curr_rnd++)
+ {
+ /* Perform ByteSub and ShiftRow operations together */
+ for (row = 0; row < 4; row++)
+ {
+ a0 = (uint32_t)aes_sbox[(data[row%4]>>24)&0xFF];
+ a1 = (uint32_t)aes_sbox[(data[(row+1)%4]>>16)&0xFF];
+ a2 = (uint32_t)aes_sbox[(data[(row+2)%4]>>8)&0xFF];
+ a3 = (uint32_t)aes_sbox[(data[(row+3)%4])&0xFF];
+
+ /* Perform MixColumn iff not last round */
+ if (curr_rnd < (rounds - 1))
+ {
+ tmp1 = a0 ^ a1 ^ a2 ^ a3;
+ old_a0 = a0;
+ a0 ^= tmp1 ^ AES_xtime(a0 ^ a1);
+ a1 ^= tmp1 ^ AES_xtime(a1 ^ a2);
+ a2 ^= tmp1 ^ AES_xtime(a2 ^ a3);
+ a3 ^= tmp1 ^ AES_xtime(a3 ^ old_a0);
+ }
+
+ tmp[row] = ((a0 << 24) | (a1 << 16) | (a2 << 8) | a3);
+ }
+
+ /* KeyAddition - note that it is vital that this loop is separate from
+ the MixColumn operation, which must be atomic...*/
+ for (row = 0; row < 4; row++)
+ data[row] = tmp[row] ^ *(k++);
+ }
+}
+
+/**
+ * Decrypt a single block (16 bytes) of data
+ */
+void AES::decrypt(uint32_t *data)
+{
+ uint32_t tmp[4];
+ uint32_t xt0,xt1,xt2,xt3,xt4,xt5,xt6;
+ uint32_t a0, a1, a2, a3, row;
+ int curr_rnd;
+ int rounds = _rounds;
+ const uint32_t *k = _ks + ((rounds+1)*4);
+
+ /* pre-round key addition */
+ for (row=4; row > 0;row--)
+ data[row-1] ^= *(--k);
+
+ /* Decrypt one block */
+ for (curr_rnd = 0; curr_rnd < rounds; curr_rnd++)
+ {
+ /* Perform ByteSub and ShiftRow operations together */
+ for (row = 4; row > 0; row--)
+ {
+ a0 = aes_isbox[(data[(row+3)%4]>>24)&0xFF];
+ a1 = aes_isbox[(data[(row+2)%4]>>16)&0xFF];
+ a2 = aes_isbox[(data[(row+1)%4]>>8)&0xFF];
+ a3 = aes_isbox[(data[row%4])&0xFF];
+
+ /* Perform MixColumn iff not last round */
+ if (curr_rnd<(rounds-1))
+ {
+ /* The MDS cofefficients (0x09, 0x0B, 0x0D, 0x0E)
+ are quite large compared to encryption; this
+ operation slows decryption down noticeably. */
+ xt0 = AES_xtime(a0^a1);
+ xt1 = AES_xtime(a1^a2);
+ xt2 = AES_xtime(a2^a3);
+ xt3 = AES_xtime(a3^a0);
+ xt4 = AES_xtime(xt0^xt1);
+ xt5 = AES_xtime(xt1^xt2);
+ xt6 = AES_xtime(xt4^xt5);
+
+ xt0 ^= a1^a2^a3^xt4^xt6;
+ xt1 ^= a0^a2^a3^xt5^xt6;
+ xt2 ^= a0^a1^a3^xt4^xt6;
+ xt3 ^= a0^a1^a2^xt5^xt6;
+ tmp[row-1] = ((xt0<<24)|(xt1<<16)|(xt2<<8)|xt3);
+ }
+ else
+ tmp[row-1] = ((a0<<24)|(a1<<16)|(a2<<8)|a3);
+ }
+
+ for (row = 4; row > 0; row--)
+ data[row-1] = tmp[row-1] ^ *(--k);
+ }
+}
+
+AES::AES(const uint8_t *key, const uint8_t *iv, AES_MODE mode, CIPHER_MODE cipherMode)
+{
+ _cipherMode = cipherMode;
+
+ int i, ii;
+ uint32_t *W, tmp, tmp2;
+ const unsigned char *ip;
+ int words;
+
+ switch (mode)
+ {
+ case AES_MODE_128:
+ i = 10;
+ words = 4;
+ break;
+
+ case AES_MODE_256:
+ i = 14;
+ words = 8;
+ break;
+
+ default: /* fail silently */
+ return;
+ }
+
+ _rounds = i;
+ _key_size = words;
+ W = _ks;
+ for (i = 0; i < words; i+=2)
+ {
+ W[i+0]= ((uint32_t)key[ 0]<<24)|
+ ((uint32_t)key[ 1]<<16)|
+ ((uint32_t)key[ 2]<< 8)|
+ ((uint32_t)key[ 3] );
+ W[i+1]= ((uint32_t)key[ 4]<<24)|
+ ((uint32_t)key[ 5]<<16)|
+ ((uint32_t)key[ 6]<< 8)|
+ ((uint32_t)key[ 7] );
+ key += 8;
+ }
+
+ ip = Rcon;
+ ii = 4 * (_rounds+1);
+ for (i = words; i<ii; i++)
+ {
+ tmp = W[i-1];
+
+ if ((i % words) == 0)
+ {
+ tmp2 =(uint32_t)aes_sbox[(tmp )&0xff]<< 8;
+ tmp2|=(uint32_t)aes_sbox[(tmp>> 8)&0xff]<<16;
+ tmp2|=(uint32_t)aes_sbox[(tmp>>16)&0xff]<<24;
+ tmp2|=(uint32_t)aes_sbox[(tmp>>24) ];
+ tmp=tmp2^(((unsigned int)*ip)<<24);
+ ip++;
+ }
+
+ if ((words == 8) && ((i % words) == 4))
+ {
+ tmp2 =(uint32_t)aes_sbox[(tmp )&0xff] ;
+ tmp2|=(uint32_t)aes_sbox[(tmp>> 8)&0xff]<< 8;
+ tmp2|=(uint32_t)aes_sbox[(tmp>>16)&0xff]<<16;
+ tmp2|=(uint32_t)aes_sbox[(tmp>>24) ]<<24;
+ tmp=tmp2;
+ }
+
+ W[i]=W[i-words]^tmp;
+ }
+
+ /* copy the iv across */
+ memcpy(_iv, iv, 16);
+
+ /* Do we need to convert the key */
+ if (_cipherMode == CIPHER_DECRYPT)
+ {
+ convertKey();
+ }
+}
+
+void AES::process(const uint8_t *in, uint8_t *out, int length)
+{
+ if (_cipherMode == CIPHER_ENCRYPT)
+ encryptCBC(in, out, length);
+ else
+ decryptCBC(in, out, length);
+}
+
+void AES::encryptCBC(const uint8_t *in, uint8_t *out, int length)
+{
+ int i;
+ uint32_t tin[4], tout[4], iv[4];
+
+ memcpy(iv, _iv, AES_IV_SIZE);
+ for (i = 0; i < 4; i++)
+ tout[i] = crypto_ntohl(iv[i]);
+
+ for (length -= AES_BLOCKSIZE; length >= 0; length -= AES_BLOCKSIZE)
+ {
+ uint32_t msg_32[4];
+ uint32_t out_32[4];
+ memcpy(msg_32, in, AES_BLOCKSIZE);
+ in += AES_BLOCKSIZE;
+
+ for (i = 0; i < 4; i++)
+ tin[i] = crypto_ntohl(msg_32[i])^tout[i];
+
+ AES::encrypt(tin);
+
+ for (i = 0; i < 4; i++)
+ {
+ tout[i] = tin[i];
+ out_32[i] = crypto_htonl(tout[i]);
+ }
+
+ memcpy(out, out_32, AES_BLOCKSIZE);
+ out += AES_BLOCKSIZE;
+ }
+
+ for (i = 0; i < 4; i++)
+ iv[i] = crypto_htonl(tout[i]);
+ memcpy(_iv, iv, AES_IV_SIZE);
+}
+
+void AES::decryptCBC(const uint8_t *in, uint8_t *out, int length)
+{
+ int i;
+ uint32_t tin[4], bufxor[4], tout[4], data[4], iv[4];
+
+ memcpy(iv, _iv, AES_IV_SIZE);
+ for (i = 0; i < 4; i++)
+ bufxor[i] = crypto_ntohl(iv[i]);
+
+ for (length -= 16; length >= 0; length -= 16)
+ {
+ uint32_t msg_32[4];
+ uint32_t out_32[4];
+ memcpy(msg_32, in, AES_BLOCKSIZE);
+ in += AES_BLOCKSIZE;
+
+ for (i = 0; i < 4; i++)
+ {
+ tin[i] = crypto_ntohl(msg_32[i]);
+ data[i] = tin[i];
+ }
+
+ AES::decrypt(data);
+
+ for (i = 0; i < 4; i++)
+ {
+ tout[i] = data[i] ^ bufxor[i];
+ bufxor[i] = tin[i];
+ out_32[i] = crypto_htonl(tout[i]);
+ }
+
+ memcpy(out, out_32, AES_BLOCKSIZE);
+ out += AES_BLOCKSIZE;
+ }
+
+ for (i = 0; i < 4; i++)
+ iv[i] = crypto_htonl(bufxor[i]);
+ memcpy(_iv, iv, AES_IV_SIZE);
+}
+
+void AES::convertKey()
+{
+ int i;
+ uint32_t *k,w,t1,t2,t3,t4;
+
+ k = _ks;
+ k += 4;
+
+ for (i= _rounds*4; i > 4; i--)
+ {
+ w= *k;
+ w = inv_mix_col(w,t1,t2,t3,t4);
+ *k++ =w;
+ }
+}
+
+/**
+ * ESP8266 specific RNG which use seems to use the hardware RNG provided on
+ * the chip
+ */
+
+void RNG::fill(uint8_t *dst, unsigned int length)
+{
+ // ESP8266 only
+ for (int i = 0; i < length; i++)
+ {
+ dst[i] = get();
+ }
+}
+
+byte RNG::get()
+{
+ // ESP8266 only
+ uint32_t* randReg = (uint32_t*) 0x3FF20E44L;
+ return (byte) *randReg;
+}
+
+uint32_t RNG::getLong()
+{
+ // ESP8266 only
+ uint32_t* randReg = (uint32_t*) 0x3FF20E44L;
+ return *randReg;
+}
+
+
+/**
+ * SHA256 HMAC
+ */
+
+SHA256HMAC::SHA256HMAC(const byte *key, unsigned int keyLen)
+{
+ // sort out the key
+ byte theKey[SHA256HMAC_BLOCKSIZE];
+ memset(theKey, 0, SHA256HMAC_BLOCKSIZE);
+ if (keyLen > SHA256HMAC_BLOCKSIZE)
+ {
+ // take a hash of the key
+ SHA256 keyHahser;
+ keyHahser.doUpdate(key, keyLen);
+ keyHahser.doFinal(theKey);
+ }
+ else
+ {
+ // we already set the buffer to 0s, so just copy keyLen
+ // bytes from key
+ memcpy(theKey, key, keyLen);
+ }
+ // explicitly zero pads
+ memset(_innerKey, 0, SHA256HMAC_BLOCKSIZE);
+ memset(_outerKey, 0, SHA256HMAC_BLOCKSIZE);
+ // compute the keys
+ blockXor(theKey, _innerKey, HMAC_IPAD, SHA256HMAC_BLOCKSIZE);
+ blockXor(theKey, _outerKey, HMAC_OPAD, SHA256HMAC_BLOCKSIZE);
+ // start the intermediate hash
+ _hash.doUpdate(_innerKey, SHA256HMAC_BLOCKSIZE);
+}
+
+void SHA256HMAC::doUpdate(const byte *msg, unsigned int len)
+{
+ _hash.doUpdate(msg, len);
+}
+
+void SHA256HMAC::doFinal(byte *digest)
+{
+ // compute the intermediate hash
+ byte interHash[SHA256_SIZE];
+ _hash.doFinal(interHash);
+ // compute the final hash
+ SHA256 finalHash;
+ finalHash.doUpdate(_outerKey, SHA256HMAC_BLOCKSIZE);
+ finalHash.doUpdate(interHash, SHA256_SIZE);
+ finalHash.doFinal(digest);
+}
+
+bool SHA256HMAC::matches(const byte *expected)
+{
+ byte theDigest[SHA256_SIZE];
+ doFinal(theDigest);
+ for (byte i = 0; i < SHA256_SIZE; i++)
+ {
+ if (expected[i] != theDigest[i])
+ return false;
+ }
+ return true;
+}
+
+void SHA256HMAC::blockXor(const byte *in, byte *out, byte val, byte len)
+{
+ for (byte i = 0; i < len; i++)
+ {
+ out[i] = in[i] ^ val;
+ }
+}
+
+
--- /dev/null
+/**
+ * An extremely minimal crypto library for Arduino devices.
+ *
+ * The SHA256 and AES implementations are derived from axTLS
+ * (http://axtls.sourceforge.net/), Copyright (c) 2008, Cameron Rich.
+ *
+ * Ported and refactored by Chris Ellis 2016.
+ *
+ */
+
+#include <Crypto.h>
+
+/**
+ * Byte order helpers
+ */
+
+
+//#if BYTE_ORDER == BIG_ENDIAN
+/*
+inline static uint16_t crypto_htons(uint16_t x)
+{
+ return x;
+}
+
+inline static uint16_t crypto_ntohs(uint16_t x)
+{
+ return x;
+}
+
+inline static uint32_t crypto_htonl(uint32_t x)
+{
+ return x;
+}
+
+inline static uint32_t crypto_ntohl(uint32_t x)
+{
+ return x;
+}
+*/
+//#else
+
+inline static uint16_t crypto_htons(uint16_t x)
+{
+ return (
+ ((x & 0xff) << 8) |
+ ((x & 0xff00) >> 8)
+ );
+}
+
+inline static uint16_t crypto_ntohs(uint16_t x)
+{
+ return (
+ ((x & 0xff) << 8) |
+ ((x & 0xff00) >> 8)
+ );
+}
+
+inline static uint32_t crypto_htonl(uint32_t x)
+{
+ return (
+ ((x & 0xff) << 24) |
+ ((x & 0xff00) << 8) |
+ ((x & 0xff0000UL) >> 8) |
+ ((x & 0xff000000UL) >> 24)
+ );
+}
+
+inline static uint32_t crypto_ntohl(uint32_t x)
+{
+ return (
+ ((x & 0xff) << 24) |
+ ((x & 0xff00) << 8) |
+ ((x & 0xff0000UL) >> 8) |
+ ((x & 0xff000000UL) >> 24)
+ );
+}
+
+//#endif
+
+#define GET_UINT32(n,b,i) \
+{ \
+ (n) = ((uint32_t) (b)[(i) ] << 24) \
+ | ((uint32_t) (b)[(i) + 1] << 16) \
+ | ((uint32_t) (b)[(i) + 2] << 8) \
+ | ((uint32_t) (b)[(i) + 3] ); \
+}
+
+#define PUT_UINT32(n,b,i) \
+{ \
+ (b)[(i) ] = (byte) ((n) >> 24); \
+ (b)[(i) + 1] = (byte) ((n) >> 16); \
+ (b)[(i) + 2] = (byte) ((n) >> 8); \
+ (b)[(i) + 3] = (byte) ((n) ); \
+}
+
+static const byte sha256_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/**
+ * Initialize the SHA256 hash
+ */
+SHA256::SHA256()
+{
+ total[0] = 0;
+ total[1] = 0;
+ state[0] = 0x6A09E667;
+ state[1] = 0xBB67AE85;
+ state[2] = 0x3C6EF372;
+ state[3] = 0xA54FF53A;
+ state[4] = 0x510E527F;
+ state[5] = 0x9B05688C;
+ state[6] = 0x1F83D9AB;
+ state[7] = 0x5BE0CD19;
+}
+
+void SHA256::SHA256_Process(const byte digest[64])
+{
+ uint32_t temp1, temp2, W[64];
+ uint32_t A, B, C, D, E, F, G, H;
+
+ GET_UINT32(W[0], digest, 0);
+ GET_UINT32(W[1], digest, 4);
+ GET_UINT32(W[2], digest, 8);
+ GET_UINT32(W[3], digest, 12);
+ GET_UINT32(W[4], digest, 16);
+ GET_UINT32(W[5], digest, 20);
+ GET_UINT32(W[6], digest, 24);
+ GET_UINT32(W[7], digest, 28);
+ GET_UINT32(W[8], digest, 32);
+ GET_UINT32(W[9], digest, 36);
+ GET_UINT32(W[10], digest, 40);
+ GET_UINT32(W[11], digest, 44);
+ GET_UINT32(W[12], digest, 48);
+ GET_UINT32(W[13], digest, 52);
+ GET_UINT32(W[14], digest, 56);
+ GET_UINT32(W[15], digest, 60);
+
+#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
+#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
+
+#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
+#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
+
+#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
+#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
+
+#define F0(x,y,z) ((x & y) | (z & (x | y)))
+#define F1(x,y,z) (z ^ (x & (y ^ z)))
+
+#define R(t) \
+( \
+ W[t] = S1(W[t - 2]) + W[t - 7] + \
+ S0(W[t - 15]) + W[t - 16] \
+)
+
+#define P(a,b,c,d,e,f,g,h,x,K) \
+{ \
+ temp1 = h + S3(e) + F1(e,f,g) + K + x; \
+ temp2 = S2(a) + F0(a,b,c); \
+ d += temp1; h = temp1 + temp2; \
+}
+
+ A = state[0];
+ B = state[1];
+ C = state[2];
+ D = state[3];
+ E = state[4];
+ F = state[5];
+ G = state[6];
+ H = state[7];
+
+ P(A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98);
+ P(H, A, B, C, D, E, F, G, W[ 1], 0x71374491);
+ P(G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF);
+ P(F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5);
+ P(E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B);
+ P(D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1);
+ P(C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4);
+ P(B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5);
+ P(A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98);
+ P(H, A, B, C, D, E, F, G, W[ 9], 0x12835B01);
+ P(G, H, A, B, C, D, E, F, W[10], 0x243185BE);
+ P(F, G, H, A, B, C, D, E, W[11], 0x550C7DC3);
+ P(E, F, G, H, A, B, C, D, W[12], 0x72BE5D74);
+ P(D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE);
+ P(C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7);
+ P(B, C, D, E, F, G, H, A, W[15], 0xC19BF174);
+ P(A, B, C, D, E, F, G, H, R(16), 0xE49B69C1);
+ P(H, A, B, C, D, E, F, G, R(17), 0xEFBE4786);
+ P(G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6);
+ P(F, G, H, A, B, C, D, E, R(19), 0x240CA1CC);
+ P(E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F);
+ P(D, E, F, G, H, A, B, C, R(21), 0x4A7484AA);
+ P(C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC);
+ P(B, C, D, E, F, G, H, A, R(23), 0x76F988DA);
+ P(A, B, C, D, E, F, G, H, R(24), 0x983E5152);
+ P(H, A, B, C, D, E, F, G, R(25), 0xA831C66D);
+ P(G, H, A, B, C, D, E, F, R(26), 0xB00327C8);
+ P(F, G, H, A, B, C, D, E, R(27), 0xBF597FC7);
+ P(E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3);
+ P(D, E, F, G, H, A, B, C, R(29), 0xD5A79147);
+ P(C, D, E, F, G, H, A, B, R(30), 0x06CA6351);
+ P(B, C, D, E, F, G, H, A, R(31), 0x14292967);
+ P(A, B, C, D, E, F, G, H, R(32), 0x27B70A85);
+ P(H, A, B, C, D, E, F, G, R(33), 0x2E1B2138);
+ P(G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC);
+ P(F, G, H, A, B, C, D, E, R(35), 0x53380D13);
+ P(E, F, G, H, A, B, C, D, R(36), 0x650A7354);
+ P(D, E, F, G, H, A, B, C, R(37), 0x766A0ABB);
+ P(C, D, E, F, G, H, A, B, R(38), 0x81C2C92E);
+ P(B, C, D, E, F, G, H, A, R(39), 0x92722C85);
+ P(A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1);
+ P(H, A, B, C, D, E, F, G, R(41), 0xA81A664B);
+ P(G, H, A, B, C, D, E, F, R(42), 0xC24B8B70);
+ P(F, G, H, A, B, C, D, E, R(43), 0xC76C51A3);
+ P(E, F, G, H, A, B, C, D, R(44), 0xD192E819);
+ P(D, E, F, G, H, A, B, C, R(45), 0xD6990624);
+ P(C, D, E, F, G, H, A, B, R(46), 0xF40E3585);
+ P(B, C, D, E, F, G, H, A, R(47), 0x106AA070);
+ P(A, B, C, D, E, F, G, H, R(48), 0x19A4C116);
+ P(H, A, B, C, D, E, F, G, R(49), 0x1E376C08);
+ P(G, H, A, B, C, D, E, F, R(50), 0x2748774C);
+ P(F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5);
+ P(E, F, G, H, A, B, C, D, R(52), 0x391C0CB3);
+ P(D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A);
+ P(C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F);
+ P(B, C, D, E, F, G, H, A, R(55), 0x682E6FF3);
+ P(A, B, C, D, E, F, G, H, R(56), 0x748F82EE);
+ P(H, A, B, C, D, E, F, G, R(57), 0x78A5636F);
+ P(G, H, A, B, C, D, E, F, R(58), 0x84C87814);
+ P(F, G, H, A, B, C, D, E, R(59), 0x8CC70208);
+ P(E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA);
+ P(D, E, F, G, H, A, B, C, R(61), 0xA4506CEB);
+ P(C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7);
+ P(B, C, D, E, F, G, H, A, R(63), 0xC67178F2);
+
+ state[0] += A;
+ state[1] += B;
+ state[2] += C;
+ state[3] += D;
+ state[4] += E;
+ state[5] += F;
+ state[6] += G;
+ state[7] += H;
+}
+
+/**
+ * Accepts an array of octets as the next portion of the message.
+ */
+void SHA256::doUpdate(const byte * msg, int len)
+{
+ uint32_t left = total[0] & 0x3F;
+ uint32_t fill = 64 - left;
+
+ total[0] += len;
+ total[0] &= 0xFFFFFFFF;
+
+ if (total[0] < len)
+ total[1]++;
+
+ if (left && len >= fill)
+ {
+ memcpy((void *) (buffer + left), (void *) msg, fill);
+ SHA256::SHA256_Process(buffer);
+ len -= fill;
+ msg += fill;
+ left = 0;
+ }
+
+ while (len >= 64)
+ {
+ SHA256::SHA256_Process(msg);
+ len -= 64;
+ msg += 64;
+ }
+
+ if (len)
+ {
+ memcpy((void *) (buffer + left), (void *) msg, len);
+ }
+}
+
+/**
+ * Return the 256-bit message digest into the user's array
+ */
+void SHA256::doFinal(byte *digest)
+{
+ uint32_t last, padn;
+ uint32_t high, low;
+ byte msglen[8];
+
+ high = (total[0] >> 29)
+ | (total[1] << 3);
+ low = (total[0] << 3);
+
+ PUT_UINT32(high, msglen, 0);
+ PUT_UINT32(low, msglen, 4);
+
+ last = total[0] & 0x3F;
+ padn = (last < 56) ? (56 - last) : (120 - last);
+
+ SHA256::doUpdate(sha256_padding, padn);
+ SHA256::doUpdate(msglen, 8);
+
+ PUT_UINT32(state[0], digest, 0);
+ PUT_UINT32(state[1], digest, 4);
+ PUT_UINT32(state[2], digest, 8);
+ PUT_UINT32(state[3], digest, 12);
+ PUT_UINT32(state[4], digest, 16);
+ PUT_UINT32(state[5], digest, 20);
+ PUT_UINT32(state[6], digest, 24);
+ PUT_UINT32(state[7], digest, 28);
+}
+
+bool SHA256::matches(const byte *expected)
+{
+ byte theDigest[SHA256_SIZE];
+ doFinal(theDigest);
+ for (byte i = 0; i < SHA256_SIZE; i++)
+ {
+ if (expected[i] != theDigest[i])
+ return false;
+ }
+ return true;
+}
+
+/******************************************************************************/
+
+#define rot1(x) (((x) << 24) | ((x) >> 8))
+#define rot2(x) (((x) << 16) | ((x) >> 16))
+#define rot3(x) (((x) << 8) | ((x) >> 24))
+
+/*
+ * This cute trick does 4 'mul by two' at once. Stolen from
+ * Dr B. R. Gladman <brg@gladman.uk.net> but I'm sure the u-(u>>7) is
+ * a standard graphics trick
+ * The key to this is that we need to xor with 0x1b if the top bit is set.
+ * a 1xxx xxxx 0xxx 0xxx First we mask the 7bit,
+ * b 1000 0000 0000 0000 then we shift right by 7 putting the 7bit in 0bit,
+ * c 0000 0001 0000 0000 we then subtract (c) from (b)
+ * d 0111 1111 0000 0000 and now we and with our mask
+ * e 0001 1011 0000 0000
+ */
+#define mt 0x80808080
+#define ml 0x7f7f7f7f
+#define mh 0xfefefefe
+#define mm 0x1b1b1b1b
+#define mul2(x,t) ((t)=((x)&mt), \
+ ((((x)+(x))&mh)^(((t)-((t)>>7))&mm)))
+
+#define inv_mix_col(x,f2,f4,f8,f9) (\
+ (f2)=mul2(x,f2), \
+ (f4)=mul2(f2,f4), \
+ (f8)=mul2(f4,f8), \
+ (f9)=(x)^(f8), \
+ (f8)=((f2)^(f4)^(f8)), \
+ (f2)^=(f9), \
+ (f4)^=(f9), \
+ (f8)^=rot3(f2), \
+ (f8)^=rot2(f4), \
+ (f8)^rot1(f9))
+
+/*
+ * AES S-box
+ */
+static const uint8_t aes_sbox[256] =
+{
+ 0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,
+ 0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76,
+ 0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0,
+ 0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0,
+ 0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC,
+ 0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15,
+ 0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,
+ 0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75,
+ 0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,
+ 0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84,
+ 0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,
+ 0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF,
+ 0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,
+ 0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8,
+ 0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,
+ 0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2,
+ 0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,
+ 0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73,
+ 0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,
+ 0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB,
+ 0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,
+ 0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79,
+ 0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,
+ 0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08,
+ 0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,
+ 0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A,
+ 0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,
+ 0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E,
+ 0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,
+ 0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF,
+ 0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,
+ 0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16,
+};
+
+/*
+ * AES is-box
+ */
+static const uint8_t aes_isbox[256] =
+{
+ 0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,
+ 0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,
+ 0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,
+ 0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb,
+ 0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,
+ 0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e,
+ 0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,
+ 0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25,
+ 0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,
+ 0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92,
+ 0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,
+ 0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84,
+ 0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,
+ 0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06,
+ 0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,
+ 0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b,
+ 0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,
+ 0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73,
+ 0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,
+ 0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e,
+ 0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,
+ 0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b,
+ 0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,
+ 0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4,
+ 0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,
+ 0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f,
+ 0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,
+ 0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef,
+ 0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,
+ 0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61,
+ 0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,
+ 0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
+};
+
+static const unsigned char Rcon[30]=
+{
+ 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,
+ 0x1b,0x36,0x6c,0xd8,0xab,0x4d,0x9a,0x2f,
+ 0x5e,0xbc,0x63,0xc6,0x97,0x35,0x6a,0xd4,
+ 0xb3,0x7d,0xfa,0xef,0xc5,0x91,
+};
+
+/* Perform doubling in Galois Field GF(2^8) using the irreducible polynomial
+ x^8+x^4+x^3+x+1 */
+static unsigned char AES_xtime(uint32_t x)
+{
+ return (x&0x80) ? (x<<1)^0x1b : x<<1;
+}
+
+
+/**
+ * Encrypt a single block (16 bytes) of data
+ */
+void AES::encrypt(uint32_t *data)
+{
+ /* To make this code smaller, generate the sbox entries on the fly.
+ * This will have a really heavy effect upon performance.
+ */
+ uint32_t tmp[4];
+ uint32_t tmp1, old_a0, a0, a1, a2, a3, row;
+ int curr_rnd;
+ int rounds = _rounds;
+ const uint32_t *k = _ks;
+
+ /* Pre-round key addition */
+ for (row = 0; row < 4; row++)
+ data[row] ^= *(k++);
+
+ /* Encrypt one block. */
+ for (curr_rnd = 0; curr_rnd < rounds; curr_rnd++)
+ {
+ /* Perform ByteSub and ShiftRow operations together */
+ for (row = 0; row < 4; row++)
+ {
+ a0 = (uint32_t)aes_sbox[(data[row%4]>>24)&0xFF];
+ a1 = (uint32_t)aes_sbox[(data[(row+1)%4]>>16)&0xFF];
+ a2 = (uint32_t)aes_sbox[(data[(row+2)%4]>>8)&0xFF];
+ a3 = (uint32_t)aes_sbox[(data[(row+3)%4])&0xFF];
+
+ /* Perform MixColumn iff not last round */
+ if (curr_rnd < (rounds - 1))
+ {
+ tmp1 = a0 ^ a1 ^ a2 ^ a3;
+ old_a0 = a0;
+ a0 ^= tmp1 ^ AES_xtime(a0 ^ a1);
+ a1 ^= tmp1 ^ AES_xtime(a1 ^ a2);
+ a2 ^= tmp1 ^ AES_xtime(a2 ^ a3);
+ a3 ^= tmp1 ^ AES_xtime(a3 ^ old_a0);
+ }
+
+ tmp[row] = ((a0 << 24) | (a1 << 16) | (a2 << 8) | a3);
+ }
+
+ /* KeyAddition - note that it is vital that this loop is separate from
+ the MixColumn operation, which must be atomic...*/
+ for (row = 0; row < 4; row++)
+ data[row] = tmp[row] ^ *(k++);
+ }
+}
+
+/**
+ * Decrypt a single block (16 bytes) of data
+ */
+void AES::decrypt(uint32_t *data)
+{
+ uint32_t tmp[4];
+ uint32_t xt0,xt1,xt2,xt3,xt4,xt5,xt6;
+ uint32_t a0, a1, a2, a3, row;
+ int curr_rnd;
+ int rounds = _rounds;
+ const uint32_t *k = _ks + ((rounds+1)*4);
+
+ /* pre-round key addition */
+ for (row=4; row > 0;row--)
+ data[row-1] ^= *(--k);
+
+ /* Decrypt one block */
+ for (curr_rnd = 0; curr_rnd < rounds; curr_rnd++)
+ {
+ /* Perform ByteSub and ShiftRow operations together */
+ for (row = 4; row > 0; row--)
+ {
+ a0 = aes_isbox[(data[(row+3)%4]>>24)&0xFF];
+ a1 = aes_isbox[(data[(row+2)%4]>>16)&0xFF];
+ a2 = aes_isbox[(data[(row+1)%4]>>8)&0xFF];
+ a3 = aes_isbox[(data[row%4])&0xFF];
+
+ /* Perform MixColumn iff not last round */
+ if (curr_rnd<(rounds-1))
+ {
+ /* The MDS cofefficients (0x09, 0x0B, 0x0D, 0x0E)
+ are quite large compared to encryption; this
+ operation slows decryption down noticeably. */
+ xt0 = AES_xtime(a0^a1);
+ xt1 = AES_xtime(a1^a2);
+ xt2 = AES_xtime(a2^a3);
+ xt3 = AES_xtime(a3^a0);
+ xt4 = AES_xtime(xt0^xt1);
+ xt5 = AES_xtime(xt1^xt2);
+ xt6 = AES_xtime(xt4^xt5);
+
+ xt0 ^= a1^a2^a3^xt4^xt6;
+ xt1 ^= a0^a2^a3^xt5^xt6;
+ xt2 ^= a0^a1^a3^xt4^xt6;
+ xt3 ^= a0^a1^a2^xt5^xt6;
+ tmp[row-1] = ((xt0<<24)|(xt1<<16)|(xt2<<8)|xt3);
+ }
+ else
+ tmp[row-1] = ((a0<<24)|(a1<<16)|(a2<<8)|a3);
+ }
+
+ for (row = 4; row > 0; row--)
+ data[row-1] = tmp[row-1] ^ *(--k);
+ }
+}
+
+AES::AES(const uint8_t *key, const uint8_t *iv, AES_MODE mode, CIPHER_MODE cipherMode)
+{
+ _cipherMode = cipherMode;
+
+ int i, ii;
+ uint32_t *W, tmp, tmp2;
+ const unsigned char *ip;
+ int words;
+
+ switch (mode)
+ {
+ case AES_MODE_128:
+ i = 10;
+ words = 4;
+ break;
+
+ case AES_MODE_256:
+ i = 14;
+ words = 8;
+ break;
+
+ default: /* fail silently */
+ return;
+ }
+
+ _rounds = i;
+ _key_size = words;
+ W = _ks;
+ for (i = 0; i < words; i+=2)
+ {
+ W[i+0]= ((uint32_t)key[ 0]<<24)|
+ ((uint32_t)key[ 1]<<16)|
+ ((uint32_t)key[ 2]<< 8)|
+ ((uint32_t)key[ 3] );
+ W[i+1]= ((uint32_t)key[ 4]<<24)|
+ ((uint32_t)key[ 5]<<16)|
+ ((uint32_t)key[ 6]<< 8)|
+ ((uint32_t)key[ 7] );
+ key += 8;
+ }
+
+ ip = Rcon;
+ ii = 4 * (_rounds+1);
+ for (i = words; i<ii; i++)
+ {
+ tmp = W[i-1];
+
+ if ((i % words) == 0)
+ {
+ tmp2 =(uint32_t)aes_sbox[(tmp )&0xff]<< 8;
+ tmp2|=(uint32_t)aes_sbox[(tmp>> 8)&0xff]<<16;
+ tmp2|=(uint32_t)aes_sbox[(tmp>>16)&0xff]<<24;
+ tmp2|=(uint32_t)aes_sbox[(tmp>>24) ];
+ tmp=tmp2^(((unsigned int)*ip)<<24);
+ ip++;
+ }
+
+ if ((words == 8) && ((i % words) == 4))
+ {
+ tmp2 =(uint32_t)aes_sbox[(tmp )&0xff] ;
+ tmp2|=(uint32_t)aes_sbox[(tmp>> 8)&0xff]<< 8;
+ tmp2|=(uint32_t)aes_sbox[(tmp>>16)&0xff]<<16;
+ tmp2|=(uint32_t)aes_sbox[(tmp>>24) ]<<24;
+ tmp=tmp2;
+ }
+
+ W[i]=W[i-words]^tmp;
+ }
+
+ /* copy the iv across */
+ memcpy(_iv, iv, 16);
+
+ /* Do we need to convert the key */
+ if (_cipherMode == CIPHER_DECRYPT)
+ {
+ convertKey();
+ }
+}
+
+void AES::process(const uint8_t *in, uint8_t *out, int length)
+{
+ if (_cipherMode == CIPHER_ENCRYPT)
+ encryptCBC(in, out, length);
+ else
+ decryptCBC(in, out, length);
+}
+
+void AES::encryptCBC(const uint8_t *in, uint8_t *out, int length)
+{
+ int i;
+ uint32_t tin[4], tout[4], iv[4];
+
+ memcpy(iv, _iv, AES_IV_SIZE);
+ for (i = 0; i < 4; i++)
+ tout[i] = crypto_ntohl(iv[i]);
+
+ for (length -= AES_BLOCKSIZE; length >= 0; length -= AES_BLOCKSIZE)
+ {
+ uint32_t msg_32[4];
+ uint32_t out_32[4];
+ memcpy(msg_32, in, AES_BLOCKSIZE);
+ in += AES_BLOCKSIZE;
+
+ for (i = 0; i < 4; i++)
+ tin[i] = crypto_ntohl(msg_32[i])^tout[i];
+
+ AES::encrypt(tin);
+
+ for (i = 0; i < 4; i++)
+ {
+ tout[i] = tin[i];
+ out_32[i] = crypto_htonl(tout[i]);
+ }
+
+ memcpy(out, out_32, AES_BLOCKSIZE);
+ out += AES_BLOCKSIZE;
+ }
+
+ for (i = 0; i < 4; i++)
+ iv[i] = crypto_htonl(tout[i]);
+ memcpy(_iv, iv, AES_IV_SIZE);
+}
+
+void AES::decryptCBC(const uint8_t *in, uint8_t *out, int length)
+{
+ int i;
+ uint32_t tin[4], bufxor[4], tout[4], data[4], iv[4];
+
+ memcpy(iv, _iv, AES_IV_SIZE);
+ for (i = 0; i < 4; i++)
+ bufxor[i] = crypto_ntohl(iv[i]);
+
+ for (length -= 16; length >= 0; length -= 16)
+ {
+ uint32_t msg_32[4];
+ uint32_t out_32[4];
+ memcpy(msg_32, in, AES_BLOCKSIZE);
+ in += AES_BLOCKSIZE;
+
+ for (i = 0; i < 4; i++)
+ {
+ tin[i] = crypto_ntohl(msg_32[i]);
+ data[i] = tin[i];
+ }
+
+ AES::decrypt(data);
+
+ for (i = 0; i < 4; i++)
+ {
+ tout[i] = data[i] ^ bufxor[i];
+ bufxor[i] = tin[i];
+ out_32[i] = crypto_htonl(tout[i]);
+ }
+
+ memcpy(out, out_32, AES_BLOCKSIZE);
+ out += AES_BLOCKSIZE;
+ }
+
+ for (i = 0; i < 4; i++)
+ iv[i] = crypto_htonl(bufxor[i]);
+ memcpy(_iv, iv, AES_IV_SIZE);
+}
+
+void AES::convertKey()
+{
+ int i;
+ uint32_t *k,w,t1,t2,t3,t4;
+
+ k = _ks;
+ k += 4;
+
+ for (i= _rounds*4; i > 4; i--)
+ {
+ w= *k;
+ w = inv_mix_col(w,t1,t2,t3,t4);
+ *k++ =w;
+ }
+}
+
+/**
+ * ESP8266 specific RNG which use seems to use the hardware RNG provided on
+ * the chip
+ */
+
+void RNG::fill(uint8_t *dst, unsigned int length)
+{
+ // ESP8266 only
+ for (int i = 0; i < length; i++)
+ {
+ dst[i] = get();
+ }
+}
+
+byte RNG::get()
+{
+ // ESP8266 only
+ uint32_t* randReg = (uint32_t*) 0x3FF20E44L;
+ return (byte) *randReg;
+}
+
+uint32_t RNG::getLong()
+{
+ // ESP8266 only
+ uint32_t* randReg = (uint32_t*) 0x3FF20E44L;
+ return *randReg;
+}
+
+
+/**
+ * SHA256 HMAC
+ */
+
+SHA256HMAC::SHA256HMAC(const byte *key, unsigned int keyLen)
+{
+ // sort out the key
+ byte theKey[SHA256HMAC_BLOCKSIZE];
+ memset(theKey, 0, SHA256HMAC_BLOCKSIZE);
+ if (keyLen > SHA256HMAC_BLOCKSIZE)
+ {
+ // take a hash of the key
+ SHA256 keyHahser;
+ keyHahser.doUpdate(key, keyLen);
+ keyHahser.doFinal(theKey);
+ }
+ else
+ {
+ // we already set the buffer to 0s, so just copy keyLen
+ // bytes from key
+ memcpy(theKey, key, keyLen);
+ }
+ // explicitly zero pads
+ memset(_innerKey, 0, SHA256HMAC_BLOCKSIZE);
+ memset(_outerKey, 0, SHA256HMAC_BLOCKSIZE);
+ // compute the keys
+ blockXor(theKey, _innerKey, HMAC_IPAD, SHA256HMAC_BLOCKSIZE);
+ blockXor(theKey, _outerKey, HMAC_OPAD, SHA256HMAC_BLOCKSIZE);
+ // start the intermediate hash
+ _hash.doUpdate(_innerKey, SHA256HMAC_BLOCKSIZE);
+}
+
+void SHA256HMAC::doUpdate(const byte *msg, unsigned int len)
+{
+ _hash.doUpdate(msg, len);
+}
+
+void SHA256HMAC::doFinal(byte *digest)
+{
+ // compute the intermediate hash
+ byte interHash[SHA256_SIZE];
+ _hash.doFinal(interHash);
+ // compute the final hash
+ SHA256 finalHash;
+ finalHash.doUpdate(_outerKey, SHA256HMAC_BLOCKSIZE);
+ finalHash.doUpdate(interHash, SHA256_SIZE);
+ finalHash.doFinal(digest);
+}
+
+bool SHA256HMAC::matches(const byte *expected)
+{
+ byte theDigest[SHA256_SIZE];
+ doFinal(theDigest);
+ for (byte i = 0; i < SHA256_SIZE; i++)
+ {
+ if (expected[i] != theDigest[i])
+ return false;
+ }
+ return true;
+}
+
+void SHA256HMAC::blockXor(const byte *in, byte *out, byte val, byte len)
+{
+ for (byte i = 0; i < len; i++)
+ {
+ out[i] = in[i] ^ val;
+ }
+}
+
+
--- /dev/null
+/**
+ * An extremely minimal crypto library for Arduino devices.
+ *
+ * The SHA256 and AES implementations are derived from axTLS
+ * (http://axtls.sourceforge.net/), Copyright (c) 2008, Cameron Rich.
+ *
+ * Ported and refactored by Chris Ellis 2016.
+ *
+ */
+
+#ifndef CRYPTO_h
+#define CRYPTO_h
+
+#include <Arduino.h>
+#include <osapi.h>
+
+#define SHA256_SIZE 32
+#define SHA256HMAC_SIZE 32
+#define SHA256HMAC_BLOCKSIZE 64
+#define AES_MAXROUNDS 14
+#define AES_BLOCKSIZE 16
+#define AES_IV_SIZE 16
+#define AES_IV_LENGTH 16
+#define AES_128_KEY_LENGTH 16
+#define AES_256_KEY_LENGTH 16
+
+/**
+ * Compute a SHA256 hash
+ */
+class SHA256
+{
+ public:
+ SHA256();
+ /**
+ * Update the hash with new data
+ */
+ void doUpdate(const byte *msg, int len);
+ void doUpdate(const char *msg, unsigned int len) { doUpdate((byte*) msg, len); }
+ void doUpdate(const char *msg) { doUpdate((byte*) msg, strlen(msg)); }
+ /**
+ * Compute the final hash and store it in [digest], digest must be
+ * at least 32 bytes
+ */
+ void doFinal(byte *digest);
+ /**
+ * Compute the final hash and check it matches this given expected hash
+ */
+ bool matches(const byte *expected);
+ private:
+ void SHA256_Process(const byte digest[64]);
+ uint32_t total[2];
+ uint32_t state[8];
+ uint8_t buffer[64];
+};
+
+#define HMAC_OPAD 0x5C
+#define HMAC_IPAD 0x36
+
+/**
+ * Compute a HMAC using SHA256
+ */
+class SHA256HMAC
+{
+ public:
+ /**
+ * Compute a SHA256 HMAC with the given [key] key of [length] bytes
+ * for authenticity
+ */
+ SHA256HMAC(const byte *key, unsigned int keyLen);
+ /**
+ * Update the hash with new data
+ */
+ void doUpdate(const byte *msg, unsigned int len);
+ void doUpdate(const char *msg, unsigned int len) { doUpdate((byte*) msg, len); }
+ void doUpdate(const char *msg) { doUpdate((byte*) msg, strlen(msg)); }
+ /**
+ * Compute the final hash and store it in [digest], digest must be
+ * at least 32 bytes
+ */
+ void doFinal(byte *digest);
+ /**
+ * Compute the final hash and check it matches this given expected hash
+ */
+ bool matches(const byte *expected);
+ private:
+ void blockXor(const byte *in, byte *out, byte val, byte len);
+ SHA256 _hash;
+ byte _innerKey[SHA256HMAC_BLOCKSIZE];
+ byte _outerKey[SHA256HMAC_BLOCKSIZE];
+};
+
+/**
+ * AES 128 and 256, based on code from axTLS
+ */
+class AES
+{
+ public:
+ typedef enum
+ {
+ AES_MODE_128,
+ AES_MODE_256
+ } AES_MODE;
+ typedef enum
+ {
+ CIPHER_ENCRYPT = 0x01,
+ CIPHER_DECRYPT = 0x02
+ } CIPHER_MODE;
+ /**
+ * Create this cipher instance in either encrypt or decrypt mode
+ *
+ * Use the given [key] which must be 16 bytes long for AES 128 and
+ * 32 bytes for AES 256
+ *
+ * Use the given [iv] initialistion vection which must be 16 bytes long
+ *
+ * Use the either AES 128 or AES 256 as specified by [mode]
+ *
+ * Either encrypt or decrypt as specified by [cipherMode]
+ */
+ AES(const uint8_t *key, const uint8_t *iv, AES_MODE mode, CIPHER_MODE cipherMode);
+ /**
+ * Either encrypt or decrypt [in] and store into [out] for [length] bytes.
+ *
+ * Note: the length must be a multiple of 16 bytes
+ */
+ void process(const uint8_t *in, uint8_t *out, int length);
+ void encryptCBC(const uint8_t *in, uint8_t *out, int length);
+ void decryptCBC(const uint8_t *in, uint8_t *out, int length);
+ void convertKey();
+ private:
+
+ void encrypt(uint32_t *data);
+ void decrypt(uint32_t *data);
+ uint16_t _rounds;
+ uint16_t _key_size;
+ uint32_t _ks[(AES_MAXROUNDS+1)*8];
+ uint8_t _iv[AES_IV_SIZE];
+ CIPHER_MODE _cipherMode;
+};
+
+/**
+ * ESP8266 specific random number generator
+ */
+class RNG
+{
+ public:
+ /**
+ * Fill the [dst] array with [length] random bytes
+ */
+ static void fill(uint8_t *dst, unsigned int length);
+ /**
+ * Get a random byte
+ */
+ static byte get();
+ /**
+ * Get a 32bit random number
+ */
+ static uint32_t getLong();
+ private:
+};
+
+#endif
--- /dev/null
+/**
+ * An extremely minimal crypto library for Arduino devices.
+ *
+ * The SHA256 and AES implementations are derived from axTLS
+ * (http://axtls.sourceforge.net/), Copyright (c) 2008, Cameron Rich.
+ *
+ * Ported and refactored by Chris Ellis 2016.
+ *
+ */
+
+#ifndef CRYPTO_h
+#define CRYPTO_h
+
+#include <Arduino.h>
+#include <osapi.h>
+
+#define SHA256_SIZE 32
+#define SHA256HMAC_SIZE 32
+#define SHA256HMAC_BLOCKSIZE 64
+#define AES_MAXROUNDS 14
+#define AES_BLOCKSIZE 16
+#define AES_IV_SIZE 16
+#define AES_IV_LENGTH 16
+#define AES_128_KEY_LENGTH 16
+#define AES_256_KEY_LENGTH 16
+
+/**
+ * Compute a SHA256 hash
+ */
+class SHA256
+{
+ public:
+ SHA256();
+ /**
+ * Update the hash with new data
+ */
+ void doUpdate(const byte *msg, int len);
+ void doUpdate(const char *msg, unsigned int len) { doUpdate((byte*) msg, len); }
+ void doUpdate(const char *msg) { doUpdate((byte*) msg, strlen(msg)); }
+ /**
+ * Compute the final hash and store it in [digest], digest must be
+ * at least 32 bytes
+ */
+ void doFinal(byte *digest);
+ /**
+ * Compute the final hash and check it matches this given expected hash
+ */
+ bool matches(const byte *expected);
+ private:
+ void SHA256_Process(const byte digest[64]);
+ uint32_t total[2];
+ uint32_t state[8];
+ uint8_t buffer[64];
+};
+
+#define HMAC_OPAD 0x5C
+#define HMAC_IPAD 0x36
+
+/**
+ * Compute a HMAC using SHA256
+ */
+class SHA256HMAC
+{
+ public:
+ /**
+ * Compute a SHA256 HMAC with the given [key] key of [length] bytes
+ * for authenticity
+ */
+ SHA256HMAC(const byte *key, unsigned int keyLen);
+ /**
+ * Update the hash with new data
+ */
+ void doUpdate(const byte *msg, unsigned int len);
+ void doUpdate(const char *msg, unsigned int len) { doUpdate((byte*) msg, len); }
+ void doUpdate(const char *msg) { doUpdate((byte*) msg, strlen(msg)); }
+ /**
+ * Compute the final hash and store it in [digest], digest must be
+ * at least 32 bytes
+ */
+ void doFinal(byte *digest);
+ /**
+ * Compute the final hash and check it matches this given expected hash
+ */
+ bool matches(const byte *expected);
+ private:
+ void blockXor(const byte *in, byte *out, byte val, byte len);
+ SHA256 _hash;
+ byte _innerKey[SHA256HMAC_BLOCKSIZE];
+ byte _outerKey[SHA256HMAC_BLOCKSIZE];
+};
+
+/**
+ * AES 128 and 256, based on code from axTLS
+ */
+class AES
+{
+ public:
+ typedef enum
+ {
+ AES_MODE_128,
+ AES_MODE_256
+ } AES_MODE;
+ typedef enum
+ {
+ CIPHER_ENCRYPT = 0x01,
+ CIPHER_DECRYPT = 0x02
+ } CIPHER_MODE;
+ /**
+ * Create this cipher instance in either encrypt or decrypt mode
+ *
+ * Use the given [key] which must be 16 bytes long for AES 128 and
+ * 32 bytes for AES 256
+ *
+ * Use the given [iv] initialistion vection which must be 16 bytes long
+ *
+ * Use the either AES 128 or AES 256 as specified by [mode]
+ *
+ * Either encrypt or decrypt as specified by [cipherMode]
+ */
+ AES(const uint8_t *key, const uint8_t *iv, AES_MODE mode, CIPHER_MODE cipherMode);
+ /**
+ * Either encrypt or decrypt [in] and store into [out] for [length] bytes.
+ *
+ * Note: the length must be a multiple of 16 bytes
+ */
+ void process(const uint8_t *in, uint8_t *out, int length);
+ private:
+ void encryptCBC(const uint8_t *in, uint8_t *out, int length);
+ void decryptCBC(const uint8_t *in, uint8_t *out, int length);
+ void convertKey();
+ void encrypt(uint32_t *data);
+ void decrypt(uint32_t *data);
+ uint16_t _rounds;
+ uint16_t _key_size;
+ uint32_t _ks[(AES_MAXROUNDS+1)*8];
+ uint8_t _iv[AES_IV_SIZE];
+ CIPHER_MODE _cipherMode;
+};
+
+/**
+ * ESP8266 specific random number generator
+ */
+class RNG
+{
+ public:
+ /**
+ * Fill the [dst] array with [length] random bytes
+ */
+ static void fill(uint8_t *dst, unsigned int length);
+ /**
+ * Get a random byte
+ */
+ static byte get();
+ /**
+ * Get a 32bit random number
+ */
+ static uint32_t getLong();
+ private:
+};
+
+#endif
--- /dev/null
+License
+=======
+Balsa SCGI
+Copyright (c) 2012, Chris Ellis
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
--- /dev/null
+# ESP8266 Crypto
+
+This is a minimal, lightweight crypto library for the ESP8266 IOT device. It
+provides the following functions:
+
+* SHA256
+* AES 128 and 256
+* SHA256HMAC
+* RNG
+
+The SHA256 and AES implementations are based upon the implementations in axTLS
+except ported to the ESP8266 Arduino platform, credit to Cameron Rich for the
+axTLS project.
+
+## Usage
+
+### SHA256HMAC
+
+The following snippet demonstrates how to compute the SHA256 HMAC authentication
+code for a message.
+
+ /* Include the crypto library into your project */
+ #include <Crypto.h>
+
+ /* The length of the key we will use for this HMAC */
+ /* The key can be of any length, 16 and 32 are common */
+ #define KEY_LENGTH 16
+
+ /* Define our */
+ byte key[KEY_LENGTH] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+
+ /* Create the HMAC instance with our key */
+ SHA256HMAC hmac(key, KEY_LENGTH);
+
+ /* Update the HMAC with just a plain string (null terminated) */
+ hmac.doUpdate("Hello World");
+
+ /* And or with a string and length */
+ const char *goodbye = "GoodBye World";
+ hmac.doUpdate(goodbye, strlen(goodbye));
+
+ /* And or with a binary message */
+ byte message[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ hmac.doUpdate(message, sizeof(message));
+
+ /* Finish the HMAC calculation and return the authentication code */
+ byte authCode[SHA256HMAC_SIZE];
+ hmac.doFinal(authCode);
+
+ /* authCode now contains our 32 byte authentication code */
+ for (byte i; i < SHA256HMAC_SIZE; i++)
+ {
+ Serial.print(authCode[i], HEX);
+ }
+
+### SHA256
+
+The following snippet demonstrates how to compute the SHA256 hash of a message.
+
+ /* Create a SHA256 hash */
+ SHA256 hasher;
+
+ /* Update the hash with your message, as many times as you like */
+ const char *hello = "Hello World";
+ hasher.doUpdate(hello, strlen(hello));
+
+ /* Update the hash with just a plain string*/
+ hasher.doUpdate("Goodbye World");
+
+ /* Update the hash with a binary message */
+ byte message[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ hasher.doUpdate(message, sizeof(message));
+
+ /* Compute the final hash */
+ byte hash[SHA256_SIZE];
+ hasher.doFinal(hash);
+
+ /* hash now contains our 32 byte hash */
+ for (byte i; i < SHA256_SIZE; i++)
+ {
+ Serial.print(hash[i], HEX);
+ }
+
+## License
+
+ESP8266 Crypto
+Copyright (c) 2016, Chris Ellis, with portions derived from axTLS
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+## Author
+
+Chris Ellis
+
+Twitter: @intrbiz
+
+Copyright (c) Chris Ellis 2016
--- /dev/null
+#include <Crypto.h>
+
+/*
+ * Compute the SHA256 hash of a message on an ESP8266
+ */
+
+void setup()
+{
+ // Setup Serial
+ Serial.begin(9600);
+ Serial.println("SHA256 example");
+
+ /* Create a SHA256 hash */
+ SHA256 hasher;
+
+ /* Update the hash with your message, as many times as you like */
+ const char *hello = "Hello World";
+ hasher.doUpdate(hello, strlen(hello));
+
+ /* Update the hash with just a plain string*/
+ hasher.doUpdate("Goodbye World");
+
+ /* Update the hash with a binary message */
+ byte message[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ hasher.doUpdate(message, sizeof(message));
+
+ /* Compute the final hash */
+ byte hash[SHA256_SIZE];
+ hasher.doFinal(hash);
+
+ /* hash now contains our 32 byte hash */
+ for (byte i=0; i < SHA256_SIZE; i++)
+ {
+ if (hash[i]<0x10) { Serial.print('0'); }
+ Serial.print(hash[i], HEX);
+ }
+}
+
+
+void loop()
+{
+
+}
--- /dev/null
+#include <Crypto.h>
+
+/*
+ * Compute the SHA256HMAC of a message on an ESP8266
+ */
+
+/* The length of the key we will use for this HMAC */
+/* The key can be of any length, 16 and 32 are common */
+#define KEY_LENGTH 16
+
+void setup()
+{
+ // Setup Serial
+ Serial.begin(9600);
+ Serial.println("SHA256HMAC example");
+
+ /* Define our */
+ byte key[KEY_LENGTH] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+
+ /* Create the HMAC instance with our key */
+ SHA256HMAC hmac(key, KEY_LENGTH);
+
+ /* Update the HMAC with just a plain string (null terminated) */
+ hmac.doUpdate("Hello World");
+
+ /* And or with a string and length */
+ const char *goodbye = "GoodBye World";
+ hmac.doUpdate(goodbye, strlen(goodbye));
+
+ /* And or with a binary message */
+ byte message[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ hmac.doUpdate(message, sizeof(message));
+
+ /* Finish the HMAC calculation and return the authentication code */
+ byte authCode[SHA256HMAC_SIZE];
+ hmac.doFinal(authCode);
+
+ /* authCode now contains our 32 byte authentication code */
+ for (byte i=0; i < SHA256HMAC_SIZE; i++)
+ {
+ if (authCode[i]<0x10) { Serial.print('0'); }
+ Serial.print(authCode[i], HEX);
+ }
+}
+
+
+void loop()
+{
+
+}
--- /dev/null
+#######################################
+# Syntax Coloring Map For Crypto
+#######################################
+
+#######################################
+# Library (KEYWORD3)
+#######################################
+
+Crypto KEYWORD3
+
+#######################################
+# Datatypes (KEYWORD1)
+#######################################
+
+SHA256 KEYWORD1
+SHA256HMAC KEYWORD1
+AES KEYWORD1
+RNG KEYWORD1
+
+#######################################
+# Methods and Functions (KEYWORD2)
+#######################################
+
+doUpdate KEYWORD2
+doFinal KEYWORD2
+matches KEYWORD2
+AES KEYWORD2
+process KEYWORD2
+fill KEYWORD2
+get KEYWORD2
+getLong KEYWORD2
+
+#######################################
+# Constants (LITERAL1)
+#######################################
+
+SHA256_SIZE LITERAL1
+SHA256HMAC_SIZE LITERAL1
+SHA256HMAC_BLOCKSIZE LITERAL1
+AES_MAXROUNDS LITERAL1
+AES_BLOCKSIZE LITERAL1
+AES_IV_SIZE LITERAL1
+AES_IV_LENGTH LITERAL1
+AES_128_KEY_LENGTH LITERAL1
+AES_256_KEY_LENGTH LITERAL1
+HMAC_OPAD LITERAL1
+HMAC_IPAD LITERAL1
--- /dev/null
+name=Crypto
+version=1.0.0
+author=Chris Ellis
+maintainer=Chris Ellis
+sentence=Very minimal crypto
+paragraph=Very minimal crypto library derived from axtls
+category=Other
+url=https://github.com/intrbiz/arduino-crypto
+architectures=esp8266
--- /dev/null
+/*
+ Boards.h - Hardware Abstraction Layer for Firmata library
+ Copyright (c) 2006-2008 Hans-Christoph Steiner. All rights reserved.
+ Copyright (C) 2009-2017 Jeff Hoefs. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+
+ Last updated August 14th, 2017
+*/
+
+#ifndef Firmata_Boards_h
+#define Firmata_Boards_h
+
+#include <inttypes.h>
+
+#if defined(ARDUINO) && ARDUINO >= 100
+#include "Arduino.h" // for digitalRead, digitalWrite, etc
+#else
+#include "WProgram.h"
+#endif
+
+// Normally Servo.h must be included before Firmata.h (which then includes
+// this file). If Servo.h wasn't included, this allows the code to still
+// compile, but without support for any Servos. Hopefully that's what the
+// user intended by not including Servo.h
+#ifndef MAX_SERVOS
+#define MAX_SERVOS 0
+#endif
+
+/*
+ Firmata Hardware Abstraction Layer
+
+Firmata is built on top of the hardware abstraction functions of Arduino,
+specifically digitalWrite, digitalRead, analogWrite, analogRead, and
+pinMode. While these functions offer simple integer pin numbers, Firmata
+needs more information than is provided by Arduino. This file provides
+all other hardware specific details. To make Firmata support a new board,
+only this file should require editing.
+
+The key concept is every "pin" implemented by Firmata may be mapped to
+any pin as implemented by Arduino. Usually a simple 1-to-1 mapping is
+best, but such mapping should not be assumed. This hardware abstraction
+layer allows Firmata to implement any number of pins which map onto the
+Arduino implemented pins in almost any arbitrary way.
+
+
+General Constants:
+
+These constants provide basic information Firmata requires.
+
+TOTAL_PINS: The total number of pins Firmata implemented by Firmata.
+ Usually this will match the number of pins the Arduino functions
+ implement, including any pins pins capable of analog or digital.
+ However, Firmata may implement any number of pins. For example,
+ on Arduino Mini with 8 analog inputs, 6 of these may be used
+ for digital functions, and 2 are analog only. On such boards,
+ Firmata can implement more pins than Arduino's pinMode()
+ function, in order to accommodate those special pins. The
+ Firmata protocol supports a maximum of 128 pins, so this
+ constant must not exceed 128.
+
+TOTAL_ANALOG_PINS: The total number of analog input pins implemented.
+ The Firmata protocol allows up to 16 analog inputs, accessed
+ using offsets 0 to 15. Because Firmata presents the analog
+ inputs using different offsets than the actual pin numbers
+ (a legacy of Arduino's analogRead function, and the way the
+ analog input capable pins are physically labeled on all
+ Arduino boards), the total number of analog input signals
+ must be specified. 16 is the maximum.
+
+VERSION_BLINK_PIN: When Firmata starts up, it will blink the version
+ number. This constant is the Arduino pin number where a
+ LED is connected.
+
+
+Pin Mapping Macros:
+
+These macros provide the mapping between pins as implemented by
+Firmata protocol and the actual pin numbers used by the Arduino
+functions. Even though such mappings are often simple, pin
+numbers received by Firmata protocol should always be used as
+input to these macros, and the result of the macro should be
+used with with any Arduino function.
+
+When Firmata is extended to support a new pin mode or feature,
+a pair of macros should be added and used for all hardware
+access. For simple 1:1 mapping, these macros add no actual
+overhead, yet their consistent use allows source code which
+uses them consistently to be easily adapted to all other boards
+with different requirements.
+
+IS_PIN_XXXX(pin): The IS_PIN macros resolve to true or non-zero
+ if a pin as implemented by Firmata corresponds to a pin
+ that actually implements the named feature.
+
+PIN_TO_XXXX(pin): The PIN_TO macros translate pin numbers as
+ implemented by Firmata to the pin numbers needed as inputs
+ to the Arduino functions. The corresponding IS_PIN macro
+ should always be tested before using a PIN_TO macro, so
+ these macros only need to handle valid Firmata pin
+ numbers for the named feature.
+
+
+Port Access Inline Funtions:
+
+For efficiency, Firmata protocol provides access to digital
+input and output pins grouped by 8 bit ports. When these
+groups of 8 correspond to actual 8 bit ports as implemented
+by the hardware, these inline functions can provide high
+speed direct port access. Otherwise, a default implementation
+using 8 calls to digitalWrite or digitalRead is used.
+
+When porting Firmata to a new board, it is recommended to
+use the default functions first and focus only on the constants
+and macros above. When those are working, if optimized port
+access is desired, these inline functions may be extended.
+The recommended approach defines a symbol indicating which
+optimization to use, and then conditional complication is
+used within these functions.
+
+readPort(port, bitmask): Read an 8 bit port, returning the value.
+ port: The port number, Firmata pins port*8 to port*8+7
+ bitmask: The actual pins to read, indicated by 1 bits.
+
+writePort(port, value, bitmask): Write an 8 bit port.
+ port: The port number, Firmata pins port*8 to port*8+7
+ value: The 8 bit value to write
+ bitmask: The actual pins to write, indicated by 1 bits.
+*/
+
+/*==============================================================================
+ * Board Specific Configuration
+ *============================================================================*/
+
+#ifndef digitalPinHasPWM
+#define digitalPinHasPWM(p) IS_PIN_DIGITAL(p)
+#endif
+
+// Arduino Duemilanove, Diecimila, and NG
+#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__)
+#if defined(NUM_ANALOG_INPUTS) && NUM_ANALOG_INPUTS == 6
+#define TOTAL_ANALOG_PINS 6
+#define TOTAL_PINS 20 // 14 digital + 6 analog
+#else
+#define TOTAL_ANALOG_PINS 8
+#define TOTAL_PINS 22 // 14 digital + 8 analog
+#endif
+#define VERSION_BLINK_PIN 13
+#define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) <= 19)
+#define IS_PIN_ANALOG(p) ((p) >= 14 && (p) < 14 + TOTAL_ANALOG_PINS)
+#define IS_PIN_PWM(p) digitalPinHasPWM(p)
+#define IS_PIN_SERVO(p) (IS_PIN_DIGITAL(p) && (p) - 2 < MAX_SERVOS)
+#define IS_PIN_I2C(p) ((p) == 18 || (p) == 19)
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) - 14)
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) ((p) - 2)
+#define ARDUINO_PINOUT_OPTIMIZE 1
+
+
+// Wiring (and board)
+#elif defined(WIRING)
+#define VERSION_BLINK_PIN WLED
+#define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) < TOTAL_PINS)
+#define IS_PIN_ANALOG(p) ((p) >= FIRST_ANALOG_PIN && (p) < (FIRST_ANALOG_PIN+TOTAL_ANALOG_PINS))
+#define IS_PIN_PWM(p) digitalPinHasPWM(p)
+#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS)
+#define IS_PIN_I2C(p) ((p) == SDA || (p) == SCL)
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) - FIRST_ANALOG_PIN)
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) (p)
+
+
+// old Arduinos
+#elif defined(__AVR_ATmega8__)
+#define TOTAL_ANALOG_PINS 6
+#define TOTAL_PINS 20 // 14 digital + 6 analog
+#define VERSION_BLINK_PIN 13
+#define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) <= 19)
+#define IS_PIN_ANALOG(p) ((p) >= 14 && (p) <= 19)
+#define IS_PIN_PWM(p) digitalPinHasPWM(p)
+#define IS_PIN_SERVO(p) (IS_PIN_DIGITAL(p) && (p) - 2 < MAX_SERVOS)
+#define IS_PIN_I2C(p) ((p) == 18 || (p) == 19)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) - 14)
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) ((p) - 2)
+#define ARDUINO_PINOUT_OPTIMIZE 1
+
+
+// Arduino Mega
+#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
+#define TOTAL_ANALOG_PINS 16
+#define TOTAL_PINS 70 // 54 digital + 16 analog
+#define VERSION_BLINK_PIN 13
+#define PIN_SERIAL1_RX 19
+#define PIN_SERIAL1_TX 18
+#define PIN_SERIAL2_RX 17
+#define PIN_SERIAL2_TX 16
+#define PIN_SERIAL3_RX 15
+#define PIN_SERIAL3_TX 14
+#define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) < TOTAL_PINS)
+#define IS_PIN_ANALOG(p) ((p) >= 54 && (p) < TOTAL_PINS)
+#define IS_PIN_PWM(p) digitalPinHasPWM(p)
+#define IS_PIN_SERVO(p) ((p) >= 2 && (p) - 2 < MAX_SERVOS)
+#define IS_PIN_I2C(p) ((p) == 20 || (p) == 21)
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define IS_PIN_SERIAL(p) ((p) > 13 && (p) < 20)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) - 54)
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) ((p) - 2)
+
+
+// Arduino DUE
+#elif defined(__SAM3X8E__)
+#define TOTAL_ANALOG_PINS 12
+#define TOTAL_PINS 66 // 54 digital + 12 analog
+#define VERSION_BLINK_PIN 13
+#define PIN_SERIAL1_RX 19
+#define PIN_SERIAL1_TX 18
+#define PIN_SERIAL2_RX 17
+#define PIN_SERIAL2_TX 16
+#define PIN_SERIAL3_RX 15
+#define PIN_SERIAL3_TX 14
+#define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) < TOTAL_PINS)
+#define IS_PIN_ANALOG(p) ((p) >= 54 && (p) < TOTAL_PINS)
+#define IS_PIN_PWM(p) digitalPinHasPWM(p)
+#define IS_PIN_SERVO(p) ((p) >= 2 && (p) - 2 < MAX_SERVOS)
+#define IS_PIN_I2C(p) ((p) == 20 || (p) == 21) // 70 71
+#define IS_PIN_SERIAL(p) ((p) > 13 && (p) < 20)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) - 54)
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) ((p) - 2)
+
+
+// Arduino/Genuino MKR1000
+#elif defined(ARDUINO_SAMD_MKR1000)
+#define TOTAL_ANALOG_PINS 7
+#define TOTAL_PINS 22 // 8 digital + 3 spi + 2 i2c + 2 uart + 7 analog
+#define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) <= 21)
+#define IS_PIN_ANALOG(p) ((p) >= 15 && (p) < 15 + TOTAL_ANALOG_PINS)
+#define IS_PIN_PWM(p) digitalPinHasPWM(p)
+#define IS_PIN_SERVO(p) (IS_PIN_DIGITAL(p) && (p) < MAX_SERVOS) // deprecated since v2.4
+#define IS_PIN_I2C(p) ((p) == 11 || (p) == 12) // SDA = 11, SCL = 12
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define IS_PIN_SERIAL(p) ((p) == PIN_SERIAL1_RX || (p) == PIN_SERIAL1_TX) //defined in variant.h RX = 13, TX = 14
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) - 15)
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) (p) // deprecated since v2.4
+
+
+// Arduino MKRZero
+#elif defined(ARDUINO_SAMD_MKRZERO)
+#define TOTAL_ANALOG_PINS 7
+#define TOTAL_PINS 34 // 8 digital + 3 spi + 2 i2c + 2 uart + 7 analog + 3 usb + 1 aref + 5 sd + 1 bottom pad + 1 led + 1 battery adc
+#define IS_PIN_DIGITAL(p) (((p) >= 0 && (p) <= 21) || (p) == 32)
+#define IS_PIN_ANALOG(p) (((p) >= 15 && (p) < 15 + TOTAL_ANALOG_PINS) || (p) == 33)
+#define IS_PIN_PWM(p) digitalPinHasPWM(p)
+#define IS_PIN_SERVO(p) (IS_PIN_DIGITAL(p) && (p) < MAX_SERVOS) // deprecated since v2.4
+#define IS_PIN_I2C(p) ((p) == 11 || (p) == 12) // SDA = 11, SCL = 12
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define IS_PIN_SERIAL(p) ((p) == PIN_SERIAL1_RX || (p) == PIN_SERIAL1_TX) //defined in variant.h RX = 13, TX = 14
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) - 15)
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) (p) // deprecated since v2.4
+
+// Arduino MKRFox1200
+#elif defined(ARDUINO_SAMD_MKRFox1200)
+#define TOTAL_ANALOG_PINS 7
+#define TOTAL_PINS 33 // 8 digital + 3 spi + 2 i2c + 2 uart + 7 analog + 3 usb + 1 aref + 5 sd + 1 bottom pad + 1 battery adc
+#define IS_PIN_DIGITAL(p) (((p) >= 0 && (p) <= 21))
+#define IS_PIN_ANALOG(p) (((p) >= 15 && (p) < 15 + TOTAL_ANALOG_PINS) || (p) == 32)
+#define IS_PIN_PWM(p) digitalPinHasPWM(p)
+#define IS_PIN_SERVO(p) (IS_PIN_DIGITAL(p) && (p) < MAX_SERVOS) // deprecated since v2.4
+#define IS_PIN_I2C(p) ((p) == 11 || (p) == 12) // SDA = 11, SCL = 12
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define IS_PIN_SERIAL(p) ((p) == PIN_SERIAL1_RX || (p) == PIN_SERIAL1_TX) //defined in variant.h RX = 13, TX = 14
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) - 15)
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) (p) // deprecated since v2.4
+
+
+// Arduino Zero
+// Note this will work with an Arduino Zero Pro, but not with an Arduino M0 Pro
+// Arduino M0 Pro does not properly map pins to the board labeled pin numbers
+#elif defined(_VARIANT_ARDUINO_ZERO_)
+#define TOTAL_ANALOG_PINS 6
+#define TOTAL_PINS 25 // 14 digital + 6 analog + 2 i2c + 3 spi
+#define TOTAL_PORTS 3 // set when TOTAL_PINS > num digitial I/O pins
+#define VERSION_BLINK_PIN LED_BUILTIN
+//#define PIN_SERIAL1_RX 0 // already defined in zero core variant.h
+//#define PIN_SERIAL1_TX 1 // already defined in zero core variant.h
+#define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) <= 19)
+#define IS_PIN_ANALOG(p) ((p) >= 14 && (p) < 14 + TOTAL_ANALOG_PINS)
+#define IS_PIN_PWM(p) digitalPinHasPWM(p)
+#define IS_PIN_SERVO(p) (IS_PIN_DIGITAL(p) && (p) < MAX_SERVOS) // deprecated since v2.4
+#define IS_PIN_I2C(p) ((p) == 20 || (p) == 21) // SDA = 20, SCL = 21
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK) // SS = A2
+#define IS_PIN_SERIAL(p) ((p) == 0 || (p) == 1)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) - 14)
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) (p) // deprecated since v2.4
+
+// Arduino Primo
+#elif defined(ARDUINO_PRIMO)
+#define TOTAL_ANALOG_PINS 6
+#define TOTAL_PINS 22 //14 digital + 6 analog + 2 i2c
+#define VERSION_BLINK_PIN LED_BUILTIN
+#define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) < 20)
+#define IS_PIN_ANALOG(p) ((p) >= 14 && (p) < 20)
+#define IS_PIN_PWM(p) digitalPinHasPWM(p)
+#define IS_PIN_SERVO(p) (IS_PIN_DIGITAL(p) && (p) < MAX_SERVOS+2)
+#define IS_PIN_I2C(p) ((p) == PIN_WIRE_SDA || (p) == PIN_WIRE_SCL) // SDA = 20, SCL = 21
+#define IS_PIN_SPI(p) ((p) == SS || (p)== MOSI || (p) == MISO || (p == SCK)) // 10, 11, 12, 13
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) - 14)
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) (p)
+
+// Arduino 101
+#elif defined(_VARIANT_ARDUINO_101_X_)
+#define TOTAL_ANALOG_PINS NUM_ANALOG_INPUTS
+#define TOTAL_PINS NUM_DIGITAL_PINS // 15 digital (including ATN pin) + 6 analog
+#define VERSION_BLINK_PIN LED_BUILTIN
+#define PIN_SERIAL1_RX 0
+#define PIN_SERIAL1_TX 1
+#define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) <= 20)
+#define IS_PIN_ANALOG(p) ((p) >= 14 && (p) < 14 + TOTAL_ANALOG_PINS)
+#define IS_PIN_PWM(p) digitalPinHasPWM(p) // 3, 5, 6, 9
+#define IS_PIN_SERVO(p) (IS_PIN_DIGITAL(p) && (p) < MAX_SERVOS) // deprecated since v2.4
+#define IS_PIN_I2C(p) ((p) == SDA || (p) == SCL) // SDA = 18, SCL = 19
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define IS_PIN_SERIAL(p) ((p) == 0 || (p) == 1)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) - 14)
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) (p) // deprecated since v2.4
+
+
+// Teensy 1.0
+#elif defined(__AVR_AT90USB162__)
+#define TOTAL_ANALOG_PINS 0
+#define TOTAL_PINS 21 // 21 digital + no analog
+#define VERSION_BLINK_PIN 6
+#define PIN_SERIAL1_RX 2
+#define PIN_SERIAL1_TX 3
+#define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) < TOTAL_PINS)
+#define IS_PIN_ANALOG(p) (0)
+#define IS_PIN_PWM(p) digitalPinHasPWM(p)
+#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS)
+#define IS_PIN_I2C(p) (0)
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define IS_PIN_SERIAL(p) ((p) == 2 || (p) == 3)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) (0)
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) (p)
+
+
+// Teensy 2.0
+#elif defined(__AVR_ATmega32U4__) && defined(CORE_TEENSY)
+#define TOTAL_ANALOG_PINS 12
+#define TOTAL_PINS 25 // 11 digital + 12 analog
+#define VERSION_BLINK_PIN 11
+#define PIN_SERIAL1_RX 7
+#define PIN_SERIAL1_TX 8
+#define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) < TOTAL_PINS)
+#define IS_PIN_ANALOG(p) ((p) >= 11 && (p) <= 22)
+#define IS_PIN_PWM(p) digitalPinHasPWM(p)
+#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS)
+#define IS_PIN_I2C(p) ((p) == 5 || (p) == 6)
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define IS_PIN_SERIAL(p) ((p) == 7 || (p) == 8)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) (((p) < 22) ? 21 - (p) : 11)
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) (p)
+
+
+// Teensy 3.5 and 3.6
+// reference: https://github.com/PaulStoffregen/cores/blob/master/teensy3/pins_arduino.h
+#elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
+#define TOTAL_ANALOG_PINS 27 // 3.5 has 27 and 3.6 has 25
+#define TOTAL_PINS 70 // 43 digital + 21 analog-digital + 6 analog (64-69)
+#define VERSION_BLINK_PIN 13
+#define PIN_SERIAL1_RX 0
+#define PIN_SERIAL1_TX 1
+#define PIN_SERIAL2_RX 9
+#define PIN_SERIAL2_TX 10
+#define PIN_SERIAL3_RX 7
+#define PIN_SERIAL3_TX 8
+// The following 2 UARTs are not yet available via SerialFirmata
+#define PIN_SERIAL4_RX 31
+#define PIN_SERIAL5_TX 32
+#define PIN_SERIAL6_RX 34
+#define PIN_SERIAL6_TX 33
+#define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) <= 63)
+#define IS_PIN_ANALOG(p) (((p) >= 14 && (p) <= 23) || ((p) >= 31 && (p) <= 39) || ((p) >= 49 && (p) <= 50) || ((p) >= 64 && (p) <= 69))
+#define IS_PIN_PWM(p) digitalPinHasPWM(p)
+#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS)
+#define IS_PIN_I2C(p) ((p) == 18 || (p) == 19)
+#define IS_PIN_SERIAL(p) (((p) > 6 && (p) < 11) || ((p) == 0 || (p) == 1))
+#define PIN_TO_DIGITAL(p) (p)
+// A0-A9 = D14-D23; A12-A20 = D31-D39; A23-A24 = D49-D50; A10-A11 = D64-D65; A21-A22 = D66-D67; A25-A26 = D68-D69
+#define PIN_TO_ANALOG(p) (((p) <= 23) ? (p) - 14 : (((p) <= 39) ? (p) - 19 : (((p) <= 50) ? (p) - 26 : (((p) <= 65) ? (p) - 55 : (((p) <= 67) ? (p) - 45 : (p) - 43)))))
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) (p)
+
+
+// Teensy 3.0, 3.1 and 3.2
+#elif defined(__MK20DX128__) || defined(__MK20DX256__)
+#define TOTAL_ANALOG_PINS 14
+#define TOTAL_PINS 38 // 24 digital + 10 analog-digital + 4 analog
+#define VERSION_BLINK_PIN 13
+#define PIN_SERIAL1_RX 0
+#define PIN_SERIAL1_TX 1
+#define PIN_SERIAL2_RX 9
+#define PIN_SERIAL2_TX 10
+#define PIN_SERIAL3_RX 7
+#define PIN_SERIAL3_TX 8
+#define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) <= 33)
+#define IS_PIN_ANALOG(p) (((p) >= 14 && (p) <= 23) || ((p) >= 34 && (p) <= 38))
+#define IS_PIN_PWM(p) digitalPinHasPWM(p)
+#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS)
+#define IS_PIN_I2C(p) ((p) == 18 || (p) == 19)
+#define IS_PIN_SERIAL(p) (((p) > 6 && (p) < 11) || ((p) == 0 || (p) == 1))
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) (((p) <= 23) ? (p) - 14 : (p) - 24)
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) (p)
+
+
+// Teensy-LC
+#elif defined(__MKL26Z64__)
+#define TOTAL_ANALOG_PINS 13
+#define TOTAL_PINS 27 // 27 digital + 13 analog-digital
+#define VERSION_BLINK_PIN 13
+#define PIN_SERIAL1_RX 0
+#define PIN_SERIAL1_TX 1
+#define PIN_SERIAL2_RX 9
+#define PIN_SERIAL2_TX 10
+#define PIN_SERIAL3_RX 7
+#define PIN_SERIAL3_TX 8
+#define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) <= 26)
+#define IS_PIN_ANALOG(p) ((p) >= 14)
+#define IS_PIN_PWM(p) digitalPinHasPWM(p)
+#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS)
+#define IS_PIN_I2C(p) ((p) == 18 || (p) == 19)
+#define IS_PIN_SERIAL(p) (((p) > 6 && (p) < 11) || ((p) == 0 || (p) == 1))
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) - 14)
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) (p)
+
+
+// Teensy++ 1.0 and 2.0
+#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
+#define TOTAL_ANALOG_PINS 8
+#define TOTAL_PINS 46 // 38 digital + 8 analog
+#define VERSION_BLINK_PIN 6
+#define PIN_SERIAL1_RX 2
+#define PIN_SERIAL1_TX 3
+#define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) < TOTAL_PINS)
+#define IS_PIN_ANALOG(p) ((p) >= 38 && (p) < TOTAL_PINS)
+#define IS_PIN_PWM(p) digitalPinHasPWM(p)
+#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS)
+#define IS_PIN_I2C(p) ((p) == 0 || (p) == 1)
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define IS_PIN_SERIAL(p) ((p) == 2 || (p) == 3)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) - 38)
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) (p)
+
+
+// Leonardo
+#elif defined(__AVR_ATmega32U4__)
+#define TOTAL_ANALOG_PINS 12
+#define TOTAL_PINS 30 // 14 digital + 12 analog + 4 SPI (D14-D17 on ISP header)
+#define VERSION_BLINK_PIN 13
+#define PIN_SERIAL1_RX 0
+#define PIN_SERIAL1_TX 1
+#define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) < TOTAL_PINS)
+#define IS_PIN_ANALOG(p) ((p) >= 18 && (p) < TOTAL_PINS)
+#define IS_PIN_PWM(p) ((p) == 3 || (p) == 5 || (p) == 6 || (p) == 9 || (p) == 10 || (p) == 11 || (p) == 13)
+#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS)
+#define IS_PIN_I2C(p) ((p) == 2 || (p) == 3)
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define IS_PIN_SERIAL(p) ((p) == 0 || (p) == 1)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) (p) - 18
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) (p)
+
+
+// Intel Galileo Board (gen 1 and 2) and Intel Edison
+#elif defined(ARDUINO_LINUX)
+#define TOTAL_ANALOG_PINS 6
+#define TOTAL_PINS 20 // 14 digital + 6 analog
+#define VERSION_BLINK_PIN 13
+#define PIN_SERIAL1_RX 0
+#define PIN_SERIAL1_TX 1
+#define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) <= 19)
+#define IS_PIN_ANALOG(p) ((p) >= 14 && (p) <= 19)
+#define IS_PIN_PWM(p) digitalPinHasPWM(p)
+#define IS_PIN_SERVO(p) (IS_PIN_DIGITAL(p) && (p) - 2 < MAX_SERVOS)
+#define IS_PIN_I2C(p) ((p) == SDA || (p) == SCL)
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define IS_PIN_SERIAL(p) ((p) == 0 || (p) == 1)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) - 14)
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) ((p) - 2)
+
+
+// RedBearLab BLE Nano with factory switch settings (S1 - S10)
+#elif defined(BLE_NANO)
+#define TOTAL_ANALOG_PINS 6
+#define TOTAL_PINS 15 // 9 digital + 3 analog
+#define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) <= 14)
+#define IS_PIN_ANALOG(p) ((p) == 8 || (p) == 9 || (p) == 10 || (p) == 11 || (p) == 12 || (p) == 14) //A0~A5
+#define IS_PIN_PWM(p) ((p) == 3 || (p) == 5 || (p) == 6)
+#define IS_PIN_SERVO(p) ((p) >= 2 && (p) <= 7)
+#define IS_PIN_I2C(p) ((p) == SDA || (p) == SCL)
+#define IS_PIN_SPI(p) ((p) == CS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) - 8)
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) (p)
+
+
+// Sanguino
+#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
+#define TOTAL_ANALOG_PINS 8
+#define TOTAL_PINS 32 // 24 digital + 8 analog
+#define VERSION_BLINK_PIN 0
+#define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) < TOTAL_PINS)
+#define IS_PIN_ANALOG(p) ((p) >= 24 && (p) < TOTAL_PINS)
+#define IS_PIN_PWM(p) digitalPinHasPWM(p)
+#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS)
+#define IS_PIN_I2C(p) ((p) == 16 || (p) == 17)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) - 24)
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) ((p) - 2)
+
+
+// Illuminato
+#elif defined(__AVR_ATmega645__)
+#define TOTAL_ANALOG_PINS 6
+#define TOTAL_PINS 42 // 36 digital + 6 analog
+#define VERSION_BLINK_PIN 13
+#define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) < TOTAL_PINS)
+#define IS_PIN_ANALOG(p) ((p) >= 36 && (p) < TOTAL_PINS)
+#define IS_PIN_PWM(p) digitalPinHasPWM(p)
+#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS)
+#define IS_PIN_I2C(p) ((p) == 4 || (p) == 5)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) - 36)
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) ((p) - 2)
+
+
+// Pic32 chipKIT FubarinoSD
+#elif defined(_BOARD_FUBARINO_SD_)
+#define TOTAL_ANALOG_PINS NUM_ANALOG_PINS // 15
+#define TOTAL_PINS NUM_DIGITAL_PINS // 45, All pins can be digital
+#define MAX_SERVOS NUM_DIGITAL_PINS
+#define VERSION_BLINK_PIN PIN_LED1
+#define IS_PIN_DIGITAL(p) 1
+#define IS_PIN_ANALOG(p) ((p) >= 30 && (p) <= 44)
+#define IS_PIN_PWM(p) IS_PIN_DIGITAL(p)
+#define IS_PIN_SERVO(p) IS_PIN_DIGITAL(p)
+#define IS_PIN_I2C(p) ((p) == 1 || (p) == 2)
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) (14 - (p - 30))
+#define PIN_TO_PWM(p) (p)
+#define PIN_TO_SERVO(p) (p)
+
+
+// Pic32 chipKIT FubarinoMini
+// Note, FubarinoMini analog pin 20 will not function in Firmata as analog input due to limitation in analog mapping
+#elif defined(_BOARD_FUBARINO_MINI_)
+#define TOTAL_ANALOG_PINS 14 // We have to fake this because of the poor analog pin mapping planning in FubarinoMini
+#define TOTAL_PINS NUM_DIGITAL_PINS // 33
+#define MAX_SERVOS NUM_DIGITAL_PINS
+#define VERSION_BLINK_PIN PIN_LED1
+#define IS_PIN_DIGITAL(p) ((p) != 14 && (p) != 15 && (p) != 31 && (p) != 32)
+#define IS_PIN_ANALOG(p) ((p) == 0 || ((p) >= 3 && (p) <= 13))
+#define IS_PIN_PWM(p) IS_PIN_DIGITAL(p)
+#define IS_PIN_SERVO(p) IS_PIN_DIGITAL(p)
+#define IS_PIN_I2C(p) ((p) == 25 || (p) == 26)
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) (p)
+#define PIN_TO_PWM(p) (p)
+#define PIN_TO_SERVO(p) (p)
+
+
+// Pic32 chipKIT UNO32
+#elif defined(_BOARD_UNO_) && defined(__PIC32) // NOTE: no _BOARD_UNO32_ to use
+#define TOTAL_ANALOG_PINS NUM_ANALOG_PINS // 12
+#define TOTAL_PINS NUM_DIGITAL_PINS // 47 All pins can be digital
+#define MAX_SERVOS NUM_DIGITAL_PINS // All pins can be servo with SoftPWMservo
+#define VERSION_BLINK_PIN PIN_LED1
+#define IS_PIN_DIGITAL(p) ((p) >= 2)
+#define IS_PIN_ANALOG(p) ((p) >= 14 && (p) <= 25)
+#define IS_PIN_PWM(p) IS_PIN_DIGITAL(p)
+#define IS_PIN_SERVO(p) IS_PIN_DIGITAL(p)
+#define IS_PIN_I2C(p) ((p) == 45 || (p) == 46)
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) - 14)
+#define PIN_TO_PWM(p) (p)
+#define PIN_TO_SERVO(p) (p)
+
+
+// Pic32 chipKIT DP32
+#elif defined(_BOARD_DP32_)
+#define TOTAL_ANALOG_PINS 15 // Really only has 9, but have to override because of mistake in variant file
+#define TOTAL_PINS NUM_DIGITAL_PINS // 19
+#define MAX_SERVOS NUM_DIGITAL_PINS // All pins can be servo with SoftPWMservo
+#define VERSION_BLINK_PIN PIN_LED1
+#define IS_PIN_DIGITAL(p) (((p) != 1) && ((p) != 4) && ((p) != 5) && ((p) != 15) && ((p) != 16))
+#define IS_PIN_ANALOG(p) ((p) >= 6 && (p) <= 14)
+#define IS_PIN_PWM(p) IS_PIN_DIGITAL(p)
+#define IS_PIN_SERVO(p) IS_PIN_DIGITAL(p)
+#define IS_PIN_I2C(p) ((p) == 2 || (p) == 3)
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) (p)
+#define PIN_TO_PWM(p) (p)
+#define PIN_TO_SERVO(p) (p)
+
+
+// Pic32 chipKIT uC32
+#elif defined(_BOARD_UC32_)
+#define TOTAL_ANALOG_PINS NUM_ANALOG_PINS // 12
+#define TOTAL_PINS NUM_DIGITAL_PINS // 47 All pins can be digital
+#define MAX_SERVOS NUM_DIGITAL_PINS // All pins can be servo with SoftPWMservo
+#define VERSION_BLINK_PIN PIN_LED1
+#define IS_PIN_DIGITAL(p) ((p) >= 2)
+#define IS_PIN_ANALOG(p) ((p) >= 14 && (p) <= 25)
+#define IS_PIN_PWM(p) IS_PIN_DIGITAL(p)
+#define IS_PIN_SERVO(p) IS_PIN_DIGITAL(p)
+#define IS_PIN_I2C(p) ((p) == 45 || (p) == 46)
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) - 14)
+#define PIN_TO_PWM(p) (p)
+#define PIN_TO_SERVO(p) (p)
+
+
+// Pic32 chipKIT WF32
+#elif defined(_BOARD_WF32_)
+#define TOTAL_ANALOG_PINS NUM_ANALOG_PINS
+#define TOTAL_PINS NUM_DIGITAL_PINS
+#define MAX_SERVOS NUM_DIGITAL_PINS
+#define VERSION_BLINK_PIN PIN_LED1
+#define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) <= 49) // Accounts for SD and WiFi dedicated pins
+#define IS_PIN_ANALOG(p) ((p) >= 14 && (p) <= 25)
+#define IS_PIN_PWM(p) IS_PIN_DIGITAL(p)
+#define IS_PIN_SERVO(p) IS_PIN_DIGITAL(p)
+#define IS_PIN_I2C(p) ((p) == 34 || (p) == 35)
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) - 14)
+#define PIN_TO_PWM(p) (p)
+#define PIN_TO_SERVO(p) (p)
+
+
+// Pic32 chipKIT WiFire
+#elif defined(_BOARD_WIFIRE_)
+#define TOTAL_ANALOG_PINS NUM_ANALOG_PINS // 14
+#define TOTAL_PINS NUM_DIGITAL_PINS // 71
+#define MAX_SERVOS NUM_DIGITAL_PINS
+#define VERSION_BLINK_PIN PIN_LED1
+#define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) <= 47) // Accounts for SD and WiFi dedicated pins
+#define IS_PIN_ANALOG(p) ((p) >= 14 && (p) <= 25)
+#define IS_PIN_PWM(p) IS_PIN_DIGITAL(p)
+#define IS_PIN_SERVO(p) IS_PIN_DIGITAL(p)
+#define IS_PIN_I2C(p) ((p) == 34 || (p) == 35)
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) <= 25 ? ((p) - 14) : (p) - 36)
+#define PIN_TO_PWM(p) (p)
+#define PIN_TO_SERVO(p) (p)
+
+
+// Pic32 chipKIT MAX32
+#elif defined(_BOARD_MEGA_) && defined(__PIC32) // NOTE: no _BOARD_MAX32_ to use
+#define TOTAL_ANALOG_PINS NUM_ANALOG_PINS // 16
+#define TOTAL_PINS NUM_DIGITAL_PINS // 87
+#define MAX_SERVOS NUM_DIGITAL_PINS
+#define VERSION_BLINK_PIN PIN_LED1
+#define IS_PIN_DIGITAL(p) ((p) >= 2)
+#define IS_PIN_ANALOG(p) ((p) >= 54 && (p) <= 69)
+#define IS_PIN_PWM(p) IS_PIN_DIGITAL(p)
+#define IS_PIN_SERVO(p) IS_PIN_DIGITAL(p)
+#define IS_PIN_I2C(p) ((p) == 34 || (p) == 35)
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) - 54)
+#define PIN_TO_PWM(p) (p)
+#define PIN_TO_SERVO(p) (p)
+
+
+// Pic32 chipKIT Pi
+#elif defined(_BOARD_CHIPKIT_PI_)
+#define TOTAL_ANALOG_PINS 16
+#define TOTAL_PINS NUM_DIGITAL_PINS // 19
+#define MAX_SERVOS NUM_DIGITAL_PINS
+#define VERSION_BLINK_PIN PIN_LED1
+#define IS_PIN_DIGITAL(p) (((p) >= 2) && ((p) <= 3) || (((p) >= 8) && ((p) <= 13)) || (((p) >= 14) && ((p) <= 17)))
+#define IS_PIN_ANALOG(p) ((p) >= 14 && (p) <= 17)
+#define IS_PIN_PWM(p) IS_PIN_DIGITAL(p)
+#define IS_PIN_SERVO(p) IS_PIN_DIGITAL(p)
+#define IS_PIN_I2C(p) ((p) == 16 || (p) == 17)
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) <= 15 ? (p) - 14 : (p) - 12)
+//#define PIN_TO_ANALOG(p) (((p) <= 16) ? ((p) - 14) : ((p) - 16))
+#define PIN_TO_PWM(p) (p)
+#define PIN_TO_SERVO(p) (p)
+
+// Pinoccio Scout
+// Note: digital pins 9-16 are usable but not labeled on the board numerically.
+// SS=9, MOSI=10, MISO=11, SCK=12, RX1=13, TX1=14, SCL=15, SDA=16
+#elif defined(ARDUINO_PINOCCIO)
+#define TOTAL_ANALOG_PINS 8
+#define TOTAL_PINS NUM_DIGITAL_PINS // 32
+#define VERSION_BLINK_PIN 23
+#define PIN_SERIAL1_RX 13
+#define PIN_SERIAL1_TX 14
+#define IS_PIN_DIGITAL(p) (((p) >= 2) && ((p) <= 16)) || (((p) >= 24) && ((p) <= 31))
+#define IS_PIN_ANALOG(p) ((p) >= 24 && (p) <= 31)
+#define IS_PIN_PWM(p) digitalPinHasPWM(p)
+#define IS_PIN_SERVO(p) IS_PIN_DIGITAL(p)
+#define IS_PIN_I2C(p) ((p) == SCL || (p) == SDA)
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define IS_PIN_SERIAL(p) ((p) == 13 || (p) == 14)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) - 24)
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) ((p) - 2)
+
+// ESP8266
+// note: boot mode GPIOs 0, 2 and 15 can be used as outputs, GPIOs 6-11 are in use for flash IO
+#elif defined(ESP8266)
+#define TOTAL_ANALOG_PINS NUM_ANALOG_INPUTS
+#define TOTAL_PINS A0 + NUM_ANALOG_INPUTS
+#define PIN_SERIAL_RX 3
+#define PIN_SERIAL_TX 1
+#define IS_PIN_DIGITAL(p) (((p) >= 0 && (p) <= 5) || ((p) >= 12 && (p) < A0))
+#define IS_PIN_ANALOG(p) ((p) >= A0 && (p) < A0 + NUM_ANALOG_INPUTS)
+#define IS_PIN_PWM(p) digitalPinHasPWM(p)
+#define IS_PIN_SERVO(p) (IS_PIN_DIGITAL(p) && (p) < MAX_SERVOS)
+#define IS_PIN_I2C(p) ((p) == SDA || (p) == SCL)
+#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
+#define IS_PIN_INTERRUPT(p) (digitalPinToInterrupt(p) > NOT_AN_INTERRUPT)
+#define IS_PIN_SERIAL(p) ((p) == PIN_SERIAL_RX || (p) == PIN_SERIAL_TX)
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ((p) - A0)
+#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
+#define PIN_TO_SERVO(p) (p)
+#define DEFAULT_PWM_RESOLUTION 10
+
+// STM32 based boards
+#elif defined(ARDUINO_ARCH_STM32)
+#define TOTAL_ANALOG_PINS NUM_ANALOG_INPUTS
+#define TOTAL_PINS NUM_DIGITAL_PINS
+#define TOTAL_PORTS MAX_NB_PORT
+#define VERSION_BLINK_PIN LED_BUILTIN
+// PIN_SERIALY_RX/TX defined in the variant.h
+#define IS_PIN_DIGITAL(p) (digitalPinIsValid(p) && !pinIsSerial(p))
+#define IS_PIN_ANALOG(p) ((p >= A0) && (p < AEND) && !pinIsSerial(p))
+#define IS_PIN_PWM(p) (IS_PIN_DIGITAL(p) && digitalPinHasPWM(p))
+#define IS_PIN_SERVO(p) IS_PIN_DIGITAL(p)
+#define IS_PIN_I2C(p) (IS_PIN_DIGITAL(p) && digitalPinHasI2C(p))
+#define IS_PIN_SPI(p) (IS_PIN_DIGITAL(p) && digitalPinHasSPI(p))
+#define IS_PIN_INTERRUPT(p) (IS_PIN_DIGITAL(p) && (digitalPinToInterrupt(p) > NOT_AN_INTERRUPT)))
+#define IS_PIN_SERIAL(p) (digitalPinHasSerial(p) && !pinIsSerial(p))
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) (p-A0)
+#define PIN_TO_PWM(p) (p)
+#define PIN_TO_SERVO(p) (p)
+#define DEFAULT_PWM_RESOLUTION PWM_RESOLUTION
+
+// Adafruit Bluefruit nRF52 boards
+#elif defined(ARDUINO_NRF52_ADAFRUIT)
+#define TOTAL_ANALOG_PINS NUM_ANALOG_INPUTS
+#define TOTAL_PINS 32
+#define VERSION_BLINK_PIN LED_BUILTIN
+#define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) < TOTAL_PINS)
+#define IS_PIN_ANALOG(p) ((p) == PIN_A0 || (p) == PIN_A1 || (p) == PIN_A2 || (p) == PIN_A3 || \
+ (p) == PIN_A4 || (p) == PIN_A5 || (p) == PIN_A6 || (p) == PIN_A7)
+#define IS_PIN_PWM(p) digitalPinHasPWM(p)
+#define IS_PIN_SERVO(p) IS_PIN_DIGITAL(p)
+#define IS_PIN_I2C(p) ((p) == PIN_WIRE_SDA || (p) == PIN_WIRE_SCL)
+#define IS_PIN_SPI(p) ((p) == SS || (p)== MOSI || (p) == MISO || (p == SCK))
+#define PIN_TO_DIGITAL(p) (p)
+#define PIN_TO_ANALOG(p) ( ((p) == PIN_A0) ? 0 : ((p) == PIN_A1) ? 1 : ((p) == PIN_A2) ? 2 : ((p) == PIN_A3) ? 3 : \
+ ((p) == PIN_A4) ? 4 : ((p) == PIN_A5) ? 5 : ((p) == PIN_A6) ? 6 : ((p) == PIN_A7) ? 7 : (127))
+#define PIN_TO_PWM(p) (p)
+#define PIN_TO_SERVO(p) (p)
+
+// anything else
+#else
+#error "Please edit Boards.h with a hardware abstraction for this board"
+#endif
+
+// as long this is not defined for all boards:
+#ifndef IS_PIN_SPI
+#define IS_PIN_SPI(p) 0
+#endif
+
+#ifndef IS_PIN_SERIAL
+#define IS_PIN_SERIAL(p) 0
+#endif
+
+#ifndef DEFAULT_PWM_RESOLUTION
+#define DEFAULT_PWM_RESOLUTION 8
+#endif
+
+/*==============================================================================
+ * readPort() - Read an 8 bit port
+ *============================================================================*/
+
+static inline unsigned char readPort(byte, byte) __attribute__((always_inline, unused));
+static inline unsigned char readPort(byte port, byte bitmask)
+{
+#if defined(ARDUINO_PINOUT_OPTIMIZE)
+ if (port == 0) return (PIND & 0xFC) & bitmask; // ignore Rx/Tx 0/1
+ if (port == 1) return ((PINB & 0x3F) | ((PINC & 0x03) << 6)) & bitmask;
+ if (port == 2) return ((PINC & 0x3C) >> 2) & bitmask;
+ return 0;
+#else
+ unsigned char out = 0, pin = port * 8;
+ if (IS_PIN_DIGITAL(pin + 0) && (bitmask & 0x01) && digitalRead(PIN_TO_DIGITAL(pin + 0))) out |= 0x01;
+ if (IS_PIN_DIGITAL(pin + 1) && (bitmask & 0x02) && digitalRead(PIN_TO_DIGITAL(pin + 1))) out |= 0x02;
+ if (IS_PIN_DIGITAL(pin + 2) && (bitmask & 0x04) && digitalRead(PIN_TO_DIGITAL(pin + 2))) out |= 0x04;
+ if (IS_PIN_DIGITAL(pin + 3) && (bitmask & 0x08) && digitalRead(PIN_TO_DIGITAL(pin + 3))) out |= 0x08;
+ if (IS_PIN_DIGITAL(pin + 4) && (bitmask & 0x10) && digitalRead(PIN_TO_DIGITAL(pin + 4))) out |= 0x10;
+ if (IS_PIN_DIGITAL(pin + 5) && (bitmask & 0x20) && digitalRead(PIN_TO_DIGITAL(pin + 5))) out |= 0x20;
+ if (IS_PIN_DIGITAL(pin + 6) && (bitmask & 0x40) && digitalRead(PIN_TO_DIGITAL(pin + 6))) out |= 0x40;
+ if (IS_PIN_DIGITAL(pin + 7) && (bitmask & 0x80) && digitalRead(PIN_TO_DIGITAL(pin + 7))) out |= 0x80;
+ return out;
+#endif
+}
+
+/*==============================================================================
+ * writePort() - Write an 8 bit port, only touch pins specified by a bitmask
+ *============================================================================*/
+
+static inline unsigned char writePort(byte, byte, byte) __attribute__((always_inline, unused));
+static inline unsigned char writePort(byte port, byte value, byte bitmask)
+{
+#if defined(ARDUINO_PINOUT_OPTIMIZE)
+ if (port == 0) {
+ bitmask = bitmask & 0xFC; // do not touch Tx & Rx pins
+ byte valD = value & bitmask;
+ byte maskD = ~bitmask;
+ cli();
+ PORTD = (PORTD & maskD) | valD;
+ sei();
+ } else if (port == 1) {
+ byte valB = (value & bitmask) & 0x3F;
+ byte valC = (value & bitmask) >> 6;
+ byte maskB = ~(bitmask & 0x3F);
+ byte maskC = ~((bitmask & 0xC0) >> 6);
+ cli();
+ PORTB = (PORTB & maskB) | valB;
+ PORTC = (PORTC & maskC) | valC;
+ sei();
+ } else if (port == 2) {
+ bitmask = bitmask & 0x0F;
+ byte valC = (value & bitmask) << 2;
+ byte maskC = ~(bitmask << 2);
+ cli();
+ PORTC = (PORTC & maskC) | valC;
+ sei();
+ }
+ return 1;
+#else
+ byte pin = port * 8;
+ if ((bitmask & 0x01)) digitalWrite(PIN_TO_DIGITAL(pin + 0), (value & 0x01));
+ if ((bitmask & 0x02)) digitalWrite(PIN_TO_DIGITAL(pin + 1), (value & 0x02));
+ if ((bitmask & 0x04)) digitalWrite(PIN_TO_DIGITAL(pin + 2), (value & 0x04));
+ if ((bitmask & 0x08)) digitalWrite(PIN_TO_DIGITAL(pin + 3), (value & 0x08));
+ if ((bitmask & 0x10)) digitalWrite(PIN_TO_DIGITAL(pin + 4), (value & 0x10));
+ if ((bitmask & 0x20)) digitalWrite(PIN_TO_DIGITAL(pin + 5), (value & 0x20));
+ if ((bitmask & 0x40)) digitalWrite(PIN_TO_DIGITAL(pin + 6), (value & 0x40));
+ if ((bitmask & 0x80)) digitalWrite(PIN_TO_DIGITAL(pin + 7), (value & 0x80));
+ return 1;
+#endif
+}
+
+
+
+
+#ifndef TOTAL_PORTS
+#define TOTAL_PORTS ((TOTAL_PINS + 7) / 8)
+#endif
+
+
+#endif /* Firmata_Boards_h */
--- /dev/null
+/*
+ Firmata.cpp - Firmata library v2.5.7 - 2017-08-19
+ Copyright (c) 2006-2008 Hans-Christoph Steiner. All rights reserved.
+ Copyright (C) 2009-2017 Jeff Hoefs. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+*/
+
+//******************************************************************************
+//* Includes
+//******************************************************************************
+
+#include "Firmata.h"
+#include "HardwareSerial.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+using namespace firmata;
+
+//******************************************************************************
+//* Static Members
+//******************************************************************************
+// make one instance for the user to use
+FirmataClass Firmata;
+
+/* callback functions */
+callbackFunction FirmataClass::currentAnalogCallback = (callbackFunction)NULL;
+callbackFunction FirmataClass::currentDigitalCallback = (callbackFunction)NULL;
+callbackFunction FirmataClass::currentPinModeCallback = (callbackFunction)NULL;
+callbackFunction FirmataClass::currentPinValueCallback = (callbackFunction)NULL;
+callbackFunction FirmataClass::currentReportAnalogCallback = (callbackFunction)NULL;
+callbackFunction FirmataClass::currentReportDigitalCallback = (callbackFunction)NULL;
+stringCallbackFunction FirmataClass::currentStringCallback = (stringCallbackFunction)NULL;
+sysexCallbackFunction FirmataClass::currentSysexCallback = (sysexCallbackFunction)NULL;
+systemCallbackFunction FirmataClass::currentSystemResetCallback = (systemCallbackFunction)NULL;
+
+//******************************************************************************
+//* Support Functions
+//******************************************************************************
+
+/**
+ * Split a 16-bit byte into two 7-bit values and write each value.
+ * @param value The 16-bit value to be split and written separately.
+ */
+void FirmataClass::sendValueAsTwo7bitBytes(int value)
+{
+ marshaller.encodeByteStream(sizeof(value), reinterpret_cast<uint8_t *>(&value), sizeof(value));
+}
+
+/**
+ * A helper method to write the beginning of a Sysex message transmission.
+ */
+void FirmataClass::startSysex(void)
+{
+ FirmataStream->write(START_SYSEX);
+}
+
+/**
+ * A helper method to write the end of a Sysex message transmission.
+ */
+void FirmataClass::endSysex(void)
+{
+ FirmataStream->write(END_SYSEX);
+}
+
+//******************************************************************************
+//* Constructors
+//******************************************************************************
+
+/**
+ * The Firmata class.
+ * An instance named "Firmata" is created automatically for the user.
+ */
+FirmataClass::FirmataClass()
+:
+ parser(FirmataParser(parserBuffer, MAX_DATA_BYTES))
+{
+ firmwareVersionCount = 0;
+ firmwareVersionVector = 0;
+ blinkVersionDisabled = false;
+
+ // Establish callback translation to parser callbacks
+ parser.attach(ANALOG_MESSAGE, (FirmataParser::callbackFunction)staticAnalogCallback, (void *)NULL);
+ parser.attach(DIGITAL_MESSAGE, (FirmataParser::callbackFunction)staticDigitalCallback, (void *)NULL);
+ parser.attach(REPORT_ANALOG, (FirmataParser::callbackFunction)staticReportAnalogCallback, (void *)NULL);
+ parser.attach(REPORT_DIGITAL, (FirmataParser::callbackFunction)staticReportDigitalCallback, (void *)NULL);
+ parser.attach(SET_PIN_MODE, (FirmataParser::callbackFunction)staticPinModeCallback, (void *)NULL);
+ parser.attach(SET_DIGITAL_PIN_VALUE, (FirmataParser::callbackFunction)staticPinValueCallback, (void *)NULL);
+ parser.attach(STRING_DATA, (FirmataParser::stringCallbackFunction)staticStringCallback, (void *)NULL);
+ parser.attach(START_SYSEX, (FirmataParser::sysexCallbackFunction)staticSysexCallback, (void *)NULL);
+ parser.attach(REPORT_FIRMWARE, (FirmataParser::versionCallbackFunction)staticReportFirmwareCallback, this);
+ parser.attach(REPORT_VERSION, (FirmataParser::systemCallbackFunction)staticReportVersionCallback, this);
+ parser.attach(SYSTEM_RESET, (FirmataParser::systemCallbackFunction)staticSystemResetCallback, (void *)NULL);
+}
+
+//******************************************************************************
+//* Public Methods
+//******************************************************************************
+
+/**
+ * Initialize the default Serial transport at the default baud of 57600.
+ */
+void FirmataClass::begin(void)
+{
+ begin(57600);
+}
+
+/**
+ * Initialize the default Serial transport and override the default baud.
+ * Sends the protocol version to the host application followed by the firmware version and name.
+ * blinkVersion is also called. To skip the call to blinkVersion, call Firmata.disableBlinkVersion()
+ * before calling Firmata.begin(baud).
+ * @param speed The baud to use. 57600 baud is the default value.
+ */
+void FirmataClass::begin(long speed)
+{
+ Serial.begin(speed);
+ blinkVersion();
+ begin(Serial);
+}
+
+/**
+ * Reassign the Firmata stream transport.
+ * @param s A reference to the Stream transport object. This can be any type of
+ * transport that implements the Stream interface. Some examples include Ethernet, WiFi
+ * and other UARTs on the board (Serial1, Serial2, etc).
+ */
+void FirmataClass::begin(Stream &s)
+{
+ FirmataStream = &s;
+ marshaller.begin(s);
+ // do not call blinkVersion() here because some hardware such as the
+ // Ethernet shield use pin 13
+ printVersion(); // send the protocol version
+ printFirmwareVersion(); // send the firmware name and version
+}
+
+/**
+ * Send the Firmata protocol version to the Firmata host application.
+ */
+void FirmataClass::printVersion(void)
+{
+ marshaller.sendVersion(FIRMATA_PROTOCOL_MAJOR_VERSION, FIRMATA_PROTOCOL_MINOR_VERSION);
+}
+
+/**
+ * Blink the Firmata protocol version to the onboard LEDs (if the board has an onboard LED).
+ * If VERSION_BLINK_PIN is not defined in Boards.h for a particular board, then this method
+ * does nothing.
+ * The first series of flashes indicates the firmware major version (2 flashes = 2).
+ * The second series of flashes indicates the firmware minor version (5 flashes = 5).
+ */
+void FirmataClass::blinkVersion(void)
+{
+#if defined(VERSION_BLINK_PIN)
+ if (blinkVersionDisabled) return;
+ // flash the pin with the protocol version
+ pinMode(VERSION_BLINK_PIN, OUTPUT);
+ strobeBlinkPin(VERSION_BLINK_PIN, FIRMATA_FIRMWARE_MAJOR_VERSION, 40, 210);
+ delay(250);
+ strobeBlinkPin(VERSION_BLINK_PIN, FIRMATA_FIRMWARE_MINOR_VERSION, 40, 210);
+ delay(125);
+#endif
+}
+
+/**
+ * Provides a means to disable the version blink sequence on the onboard LED, trimming startup
+ * time by a couple of seconds.
+ * Call this before Firmata.begin(). It only applies when using the default Serial transport.
+ */
+void FirmataClass::disableBlinkVersion()
+{
+ blinkVersionDisabled = true;
+}
+
+/**
+ * Sends the firmware name and version to the Firmata host application. The major and minor version
+ * numbers are the first 2 bytes in the message. The following bytes are the characters of the
+ * firmware name.
+ */
+void FirmataClass::printFirmwareVersion(void)
+{
+ if (firmwareVersionCount) { // make sure that the name has been set before reporting
+ marshaller.sendFirmwareVersion(static_cast<uint8_t>(firmwareVersionVector[0]), static_cast<uint8_t>(firmwareVersionVector[1]), (firmwareVersionCount - 2), reinterpret_cast<uint8_t *>(&firmwareVersionVector[2]));
+ }
+}
+
+/**
+ * Sets the name and version of the firmware. This is not the same version as the Firmata protocol
+ * (although at times the firmware version and protocol version may be the same number).
+ * @param name A pointer to the name char array
+ * @param major The major version number
+ * @param minor The minor version number
+ */
+void FirmataClass::setFirmwareNameAndVersion(const char *name, byte major, byte minor)
+{
+ const char *firmwareName;
+ const char *extension;
+
+ // parse out ".cpp" and "applet/" that comes from using __FILE__
+ extension = strstr(name, ".cpp");
+ firmwareName = strrchr(name, '/');
+
+ if (!firmwareName) {
+ // windows
+ firmwareName = strrchr(name, '\\');
+ }
+ if (!firmwareName) {
+ // user passed firmware name
+ firmwareName = name;
+ } else {
+ firmwareName ++;
+ }
+
+ if (!extension) {
+ firmwareVersionCount = strlen(firmwareName) + 2;
+ } else {
+ firmwareVersionCount = extension - firmwareName + 2;
+ }
+
+ // in case anyone calls setFirmwareNameAndVersion more than once
+ free(firmwareVersionVector);
+
+ firmwareVersionVector = (byte *) malloc(firmwareVersionCount + 1);
+ firmwareVersionVector[firmwareVersionCount] = 0;
+ firmwareVersionVector[0] = major;
+ firmwareVersionVector[1] = minor;
+ strncpy((char *)firmwareVersionVector + 2, firmwareName, firmwareVersionCount - 2);
+}
+
+//------------------------------------------------------------------------------
+// Serial Receive Handling
+
+/**
+ * A wrapper for Stream::available()
+ * @return The number of bytes remaining in the input stream buffer.
+ */
+int FirmataClass::available(void)
+{
+ return FirmataStream->available();
+}
+
+/**
+ * Read a single int from the input stream. If the value is not = -1, pass it on to parse(byte)
+ */
+void FirmataClass::processInput(void)
+{
+ int inputData = FirmataStream->read(); // this is 'int' to handle -1 when no data
+ if (inputData != -1) {
+ parser.parse(inputData);
+ }
+}
+
+/**
+ * Parse data from the input stream.
+ * @param inputData A single byte to be added to the parser.
+ */
+void FirmataClass::parse(byte inputData)
+{
+ parser.parse(inputData);
+}
+
+/**
+ * @return Returns true if the parser is actively parsing data.
+ */
+boolean FirmataClass::isParsingMessage(void)
+{
+ return parser.isParsingMessage();
+}
+
+//------------------------------------------------------------------------------
+// Output Stream Handling
+
+/**
+ * Send an analog message to the Firmata host application. The range of pins is limited to [0..15]
+ * when using the ANALOG_MESSAGE. The maximum value of the ANALOG_MESSAGE is limited to 14 bits
+ * (16384). To increase the pin range or value, see the documentation for the EXTENDED_ANALOG
+ * message.
+ * @param pin The analog pin to send the value of (limited to pins 0 - 15).
+ * @param value The value of the analog pin (0 - 1024 for 10-bit analog, 0 - 4096 for 12-bit, etc).
+ * The maximum value is 14-bits (16384).
+ */
+void FirmataClass::sendAnalog(byte pin, int value)
+{
+ marshaller.sendAnalog(pin, value);
+}
+
+/* (intentionally left out asterix here)
+ * STUB - NOT IMPLEMENTED
+ * Send a single digital pin value to the Firmata host application.
+ * @param pin The digital pin to send the value of.
+ * @param value The value of the pin.
+ */
+void FirmataClass::sendDigital(byte pin, int value)
+{
+ (void)pin;
+ (void)value;
+ /* TODO add single pin digital messages to the protocol, this needs to
+ * track the last digital data sent so that it can be sure to change just
+ * one bit in the packet. This is complicated by the fact that the
+ * numbering of the pins will probably differ on Arduino, Wiring, and
+ * other boards.
+ */
+
+ // TODO: the digital message should not be sent on the serial port every
+ // time sendDigital() is called. Instead, it should add it to an int
+ // which will be sent on a schedule. If a pin changes more than once
+ // before the digital message is sent on the serial port, it should send a
+ // digital message for each change.
+
+ // if(value == 0)
+ // sendDigitalPortPair();
+}
+
+
+/**
+ * Send an 8-bit port in a single digital message (protocol v2 and later).
+ * Send 14-bits in a single digital message (protocol v1).
+ * @param portNumber The port number to send. Note that this is not the same as a "port" on the
+ * physical microcontroller. Ports are defined in order per every 8 pins in ascending order
+ * of the Arduino digital pin numbering scheme. Port 0 = pins D0 - D7, port 1 = pins D8 - D15, etc.
+ * @param portData The value of the port. The value of each pin in the port is represented by a bit.
+ */
+void FirmataClass::sendDigitalPort(byte portNumber, int portData)
+{
+ marshaller.sendDigitalPort(portNumber, portData);
+}
+
+/**
+ * Send a sysex message where all values after the command byte are packet as 2 7-bit bytes
+ * (this is not always the case so this function is not always used to send sysex messages).
+ * @param command The sysex command byte.
+ * @param bytec The number of data bytes in the message (excludes start, command and end bytes).
+ * @param bytev A pointer to the array of data bytes to send in the message.
+ */
+void FirmataClass::sendSysex(byte command, byte bytec, byte *bytev)
+{
+ marshaller.sendSysex(command, bytec, bytev);
+}
+
+/**
+ * Send a string to the Firmata host application.
+ * @param command Must be STRING_DATA
+ * @param string A pointer to the char string
+ */
+void FirmataClass::sendString(byte command, const char *string)
+{
+ if (command == STRING_DATA) {
+ marshaller.sendString(string);
+ }
+}
+
+/**
+ * Send a string to the Firmata host application.
+ * @param string A pointer to the char string
+ */
+void FirmataClass::sendString(const char *string)
+{
+ marshaller.sendString(string);
+}
+
+/**
+ * A wrapper for Stream::available().
+ * Write a single byte to the output stream.
+ * @param c The byte to be written.
+ */
+void FirmataClass::write(byte c)
+{
+ FirmataStream->write(c);
+}
+
+/**
+ * Attach a generic sysex callback function to a command (options are: ANALOG_MESSAGE,
+ * DIGITAL_MESSAGE, REPORT_ANALOG, REPORT DIGITAL, SET_PIN_MODE and SET_DIGITAL_PIN_VALUE).
+ * @param command The ID of the command to attach a callback function to.
+ * @param newFunction A reference to the callback function to attach.
+ */
+void FirmataClass::attach(uint8_t command, ::callbackFunction newFunction)
+{
+ switch (command) {
+ case ANALOG_MESSAGE:
+ currentAnalogCallback = newFunction;
+ break;
+ case DIGITAL_MESSAGE:
+ currentDigitalCallback = newFunction;
+ break;
+ case REPORT_ANALOG:
+ currentReportAnalogCallback = newFunction;
+ break;
+ case REPORT_DIGITAL:
+ currentReportDigitalCallback = newFunction;
+ break;
+ case SET_PIN_MODE:
+ currentPinModeCallback = newFunction;
+ break;
+ case SET_DIGITAL_PIN_VALUE:
+ currentPinValueCallback = newFunction;
+ break;
+ }
+}
+
+/**
+ * Attach a callback function for the SYSTEM_RESET command.
+ * @param command Must be set to SYSTEM_RESET or it will be ignored.
+ * @param newFunction A reference to the system reset callback function to attach.
+ */
+void FirmataClass::attach(uint8_t command, systemCallbackFunction newFunction)
+{
+ switch (command) {
+ case SYSTEM_RESET:
+ currentSystemResetCallback = newFunction;
+ break;
+ }
+}
+
+/**
+ * Attach a callback function for the STRING_DATA command.
+ * @param command Must be set to STRING_DATA or it will be ignored.
+ * @param newFunction A reference to the string callback function to attach.
+ */
+void FirmataClass::attach(uint8_t command, stringCallbackFunction newFunction)
+{
+ switch (command) {
+ case STRING_DATA:
+ currentStringCallback = newFunction;
+ break;
+ }
+}
+
+/**
+ * Attach a generic sysex callback function to sysex command.
+ * @param command The ID of the command to attach a callback function to.
+ * @param newFunction A reference to the sysex callback function to attach.
+ */
+void FirmataClass::attach(uint8_t command, sysexCallbackFunction newFunction)
+{
+ (void)command;
+ currentSysexCallback = newFunction;
+}
+
+/**
+ * Detach a callback function for a specified command (such as SYSTEM_RESET, STRING_DATA,
+ * ANALOG_MESSAGE, DIGITAL_MESSAGE, etc).
+ * @param command The ID of the command to detatch the callback function from.
+ */
+void FirmataClass::detach(uint8_t command)
+{
+ switch (command) {
+ case SYSTEM_RESET:
+ attach(command, (systemCallbackFunction)NULL);
+ break;
+ case STRING_DATA:
+ attach(command, (stringCallbackFunction)NULL);
+ break;
+ case START_SYSEX:
+ attach(command, (sysexCallbackFunction)NULL);
+ break;
+ default:
+ attach(command, (callbackFunction)NULL);
+ break;
+ }
+}
+
+/**
+ * @param pin The pin to get the configuration of.
+ * @return The configuration of the specified pin.
+ */
+byte FirmataClass::getPinMode(byte pin)
+{
+ return pinConfig[pin];
+}
+
+/**
+ * Set the pin mode/configuration. The pin configuration (or mode) in Firmata represents the
+ * current function of the pin. Examples are digital input or output, analog input, pwm, i2c,
+ * serial (uart), etc.
+ * @param pin The pin to configure.
+ * @param config The configuration value for the specified pin.
+ */
+void FirmataClass::setPinMode(byte pin, byte config)
+{
+ if (pinConfig[pin] == PIN_MODE_IGNORE)
+ return;
+
+ pinConfig[pin] = config;
+}
+
+/**
+ * @param pin The pin to get the state of.
+ * @return The state of the specified pin.
+ */
+int FirmataClass::getPinState(byte pin)
+{
+ return pinState[pin];
+}
+
+/**
+ * Set the pin state. The pin state of an output pin is the pin value. The state of an
+ * input pin is 0, unless the pin has it's internal pull up resistor enabled, then the value is 1.
+ * @param pin The pin to set the state of
+ * @param state Set the state of the specified pin
+ */
+void FirmataClass::setPinState(byte pin, int state)
+{
+ pinState[pin] = state;
+}
+
+// sysex callbacks
+/*
+ * this is too complicated for analogReceive, but maybe for Sysex?
+ void FirmataClass::attachSysex(sysexFunction newFunction)
+ {
+ byte i;
+ byte tmpCount = analogReceiveFunctionCount;
+ analogReceiveFunction* tmpArray = analogReceiveFunctionArray;
+ analogReceiveFunctionCount++;
+ analogReceiveFunctionArray = (analogReceiveFunction*) calloc(analogReceiveFunctionCount, sizeof(analogReceiveFunction));
+ for(i = 0; i < tmpCount; i++) {
+ analogReceiveFunctionArray[i] = tmpArray[i];
+ }
+ analogReceiveFunctionArray[tmpCount] = newFunction;
+ free(tmpArray);
+ }
+*/
+
+//******************************************************************************
+//* Private Methods
+//******************************************************************************
+
+/**
+ * Flashing the pin for the version number
+ * @private
+ * @param pin The pin the LED is attached to.
+ * @param count The number of times to flash the LED.
+ * @param onInterval The number of milliseconds for the LED to be ON during each interval.
+ * @param offInterval The number of milliseconds for the LED to be OFF during each interval.
+ */
+void FirmataClass::strobeBlinkPin(byte pin, int count, int onInterval, int offInterval)
+{
+ byte i;
+ for (i = 0; i < count; i++) {
+ delay(offInterval);
+ digitalWrite(pin, HIGH);
+ delay(onInterval);
+ digitalWrite(pin, LOW);
+ }
+}
+
--- /dev/null
+/*
+ Firmata.h - Firmata library v2.5.7 - 2017-08-19
+ Copyright (c) 2006-2008 Hans-Christoph Steiner. All rights reserved.
+ Copyright (C) 2009-2017 Jeff Hoefs. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+*/
+
+#ifndef Firmata_h
+#define Firmata_h
+
+#include "Boards.h" /* Hardware Abstraction Layer + Wiring/Arduino */
+#include "FirmataDefines.h"
+#include "FirmataMarshaller.h"
+#include "FirmataParser.h"
+
+/* DEPRECATED as of Firmata v2.5.1. As of 2.5.1 there are separate version numbers for
+ * the protocol version and the firmware version.
+ */
+#define FIRMATA_MAJOR_VERSION 2 // same as FIRMATA_PROTOCOL_MAJOR_VERSION
+#define FIRMATA_MINOR_VERSION 5 // same as FIRMATA_PROTOCOL_MINOR_VERSION
+#define FIRMATA_BUGFIX_VERSION 1 // same as FIRMATA_PROTOCOL_BUGFIX_VERSION
+
+// extended command set using sysex (0-127/0x00-0x7F)
+/* 0x00-0x0F reserved for user-defined commands */
+// these are DEPRECATED to make the naming more consistent
+#define FIRMATA_STRING 0x71 // same as STRING_DATA
+#define SYSEX_I2C_REQUEST 0x76 // same as I2C_REQUEST
+#define SYSEX_I2C_REPLY 0x77 // same as I2C_REPLY
+#define SYSEX_SAMPLING_INTERVAL 0x7A // same as SAMPLING_INTERVAL
+
+// pin modes
+//#define INPUT 0x00 // defined in Arduino.h
+//#define OUTPUT 0x01 // defined in Arduino.h
+// DEPRECATED as of Firmata v2.5
+#define ANALOG 0x02 // same as PIN_MODE_ANALOG
+#define PWM 0x03 // same as PIN_MODE_PWM
+#define SERVO 0x04 // same as PIN_MODE_SERVO
+#define SHIFT 0x05 // same as PIN_MODE_SHIFT
+#define I2C 0x06 // same as PIN_MODE_I2C
+#define ONEWIRE 0x07 // same as PIN_MODE_ONEWIRE
+#define STEPPER 0x08 // same as PIN_MODE_STEPPER
+#define ENCODER 0x09 // same as PIN_MODE_ENCODER
+#define IGNORE 0x7F // same as PIN_MODE_IGNORE
+
+namespace firmata {
+
+// TODO make it a subclass of a generic Serial/Stream base class
+class FirmataClass
+{
+ public:
+ typedef void (*callbackFunction)(uint8_t, int);
+ typedef void (*systemCallbackFunction)(void);
+ typedef void (*stringCallbackFunction)(char *);
+ typedef void (*sysexCallbackFunction)(uint8_t command, uint8_t argc, uint8_t *argv);
+
+ FirmataClass();
+
+ /* Arduino constructors */
+ void begin();
+ void begin(long);
+ void begin(Stream &s);
+
+ /* querying functions */
+ void printVersion(void);
+ void blinkVersion(void);
+ void printFirmwareVersion(void);
+
+ //void setFirmwareVersion(byte major, byte minor); // see macro below
+ void setFirmwareNameAndVersion(const char *name, byte major, byte minor);
+ void disableBlinkVersion();
+
+ /* serial receive handling */
+ int available(void);
+ void processInput(void);
+ void parse(unsigned char value);
+ boolean isParsingMessage(void);
+
+ /* serial send handling */
+ void sendAnalog(byte pin, int value);
+ void sendDigital(byte pin, int value); // TODO implement this
+ void sendDigitalPort(byte portNumber, int portData);
+ void sendString(const char *string);
+ void sendString(byte command, const char *string);
+ void sendSysex(byte command, byte bytec, byte *bytev);
+ void write(byte c);
+
+ /* attach & detach callback functions to messages */
+ void attach(uint8_t command, callbackFunction newFunction);
+ void attach(uint8_t command, systemCallbackFunction newFunction);
+ void attach(uint8_t command, stringCallbackFunction newFunction);
+ void attach(uint8_t command, sysexCallbackFunction newFunction);
+ void detach(uint8_t command);
+
+ /* access pin state and config */
+ byte getPinMode(byte pin);
+ void setPinMode(byte pin, byte config);
+
+ /* access pin state */
+ int getPinState(byte pin);
+ void setPinState(byte pin, int state);
+
+ /* utility methods */
+ void sendValueAsTwo7bitBytes(int value);
+ void startSysex(void);
+ void endSysex(void);
+
+ private:
+ uint8_t parserBuffer[MAX_DATA_BYTES];
+ FirmataMarshaller marshaller;
+ FirmataParser parser;
+ Stream *FirmataStream;
+
+ /* firmware name and version */
+ byte firmwareVersionCount;
+ byte *firmwareVersionVector;
+
+ /* pin configuration */
+ byte pinConfig[TOTAL_PINS];
+ int pinState[TOTAL_PINS];
+
+ boolean blinkVersionDisabled;
+
+ /* private methods ------------------------------ */
+ void strobeBlinkPin(byte pin, int count, int onInterval, int offInterval);
+ friend void FirmataMarshaller::encodeByteStream (size_t bytec, uint8_t * bytev, size_t max_bytes = 0) const;
+
+ /* callback functions */
+ static callbackFunction currentAnalogCallback;
+ static callbackFunction currentDigitalCallback;
+ static callbackFunction currentPinModeCallback;
+ static callbackFunction currentPinValueCallback;
+ static callbackFunction currentReportAnalogCallback;
+ static callbackFunction currentReportDigitalCallback;
+ static stringCallbackFunction currentStringCallback;
+ static sysexCallbackFunction currentSysexCallback;
+ static systemCallbackFunction currentSystemResetCallback;
+
+ /* static callbacks */
+ inline static void staticAnalogCallback (void *, uint8_t command, uint16_t value) { if ( currentAnalogCallback ) { currentAnalogCallback(command,(int)value); } }
+ inline static void staticDigitalCallback (void *, uint8_t command, uint16_t value) { if ( currentDigitalCallback ) { currentDigitalCallback(command, (int)value); } }
+ inline static void staticPinModeCallback (void *, uint8_t command, uint16_t value) { if ( currentPinModeCallback ) { currentPinModeCallback(command, (int)value); } }
+ inline static void staticPinValueCallback (void *, uint8_t command, uint16_t value) { if ( currentPinValueCallback ) { currentPinValueCallback(command, (int)value); } }
+ inline static void staticReportAnalogCallback (void *, uint8_t command, uint16_t value) { if ( currentReportAnalogCallback ) { currentReportAnalogCallback(command, (int)value); } }
+ inline static void staticReportDigitalCallback (void *, uint8_t command, uint16_t value) { if ( currentReportDigitalCallback ) { currentReportDigitalCallback(command, (int)value); } }
+ inline static void staticStringCallback (void *, const char * c_str) { if ( currentStringCallback ) { currentStringCallback((char *)c_str); } }
+ inline static void staticSysexCallback (void *, uint8_t command, size_t argc, uint8_t *argv) { if ( currentSysexCallback ) { currentSysexCallback(command, (uint8_t)argc, argv); } }
+ inline static void staticReportFirmwareCallback (void * context, size_t, size_t, const char *) { if ( context ) { ((FirmataClass *)context)->printFirmwareVersion(); } }
+ inline static void staticReportVersionCallback (void * context) { if ( context ) { ((FirmataClass *)context)->printVersion(); } }
+ inline static void staticSystemResetCallback (void *) { if ( currentSystemResetCallback ) { currentSystemResetCallback(); } }
+};
+
+} // namespace firmata
+
+extern "C" {
+ // callback function types
+ typedef firmata::FirmataClass::callbackFunction callbackFunction;
+ typedef firmata::FirmataClass::systemCallbackFunction systemCallbackFunction;
+ typedef firmata::FirmataClass::stringCallbackFunction stringCallbackFunction;
+ typedef firmata::FirmataClass::sysexCallbackFunction sysexCallbackFunction;
+}
+
+extern firmata::FirmataClass Firmata;
+
+/*==============================================================================
+ * MACROS
+ *============================================================================*/
+
+/* shortcut for setFirmwareNameAndVersion() that uses __FILE__ to set the
+ * firmware name. It needs to be a macro so that __FILE__ is included in the
+ * firmware source file rather than the library source file.
+ */
+#define setFirmwareVersion(x, y) setFirmwareNameAndVersion(__FILE__, x, y)
+
+#endif /* Firmata_h */
--- /dev/null
+/*
+ FirmataConstants.h
+ Copyright (c) 2006-2008 Hans-Christoph Steiner. All rights reserved.
+ Copyright (C) 2009-2017 Jeff Hoefs. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+*/
+
+#ifndef FirmataConstants_h
+#define FirmataConstants_h
+
+namespace firmata {
+/* Version numbers for the Firmata library.
+ * The firmware version will not always equal the protocol version going forward.
+ * Query using the REPORT_FIRMWARE message.
+ */
+static const int FIRMWARE_MAJOR_VERSION = 2;
+static const int FIRMWARE_MINOR_VERSION = 5;
+static const int FIRMWARE_BUGFIX_VERSION = 7;
+
+/* Version numbers for the protocol. The protocol is still changing, so these
+ * version numbers are important.
+ * Query using the REPORT_VERSION message.
+ */
+static const int PROTOCOL_MAJOR_VERSION = 2; // for non-compatible changes
+static const int PROTOCOL_MINOR_VERSION = 5; // for backwards compatible changes
+static const int PROTOCOL_BUGFIX_VERSION = 1; // for bugfix releases
+
+static const int MAX_DATA_BYTES = 64; // max number of data bytes in incoming messages
+
+// message command bytes (128-255/0x80-0xFF)
+
+static const int DIGITAL_MESSAGE = 0x90; // send data for a digital port (collection of 8 pins)
+static const int ANALOG_MESSAGE = 0xE0; // send data for an analog pin (or PWM)
+static const int REPORT_ANALOG = 0xC0; // enable analog input by pin #
+static const int REPORT_DIGITAL = 0xD0; // enable digital input by port pair
+//
+static const int SET_PIN_MODE = 0xF4; // set a pin to INPUT/OUTPUT/PWM/etc
+static const int SET_DIGITAL_PIN_VALUE = 0xF5; // set value of an individual digital pin
+//
+static const int REPORT_VERSION = 0xF9; // report protocol version
+static const int SYSTEM_RESET = 0xFF; // reset from MIDI
+//
+static const int START_SYSEX = 0xF0; // start a MIDI Sysex message
+static const int END_SYSEX = 0xF7; // end a MIDI Sysex message
+
+// extended command set using sysex (0-127/0x00-0x7F)
+/* 0x00-0x0F reserved for user-defined commands */
+
+static const int SERIAL_DATA = 0x60; // communicate with serial devices, including other boards
+static const int ENCODER_DATA = 0x61; // reply with encoders current positions
+static const int SERVO_CONFIG = 0x70; // set max angle, minPulse, maxPulse, freq
+static const int STRING_DATA = 0x71; // a string message with 14-bits per char
+static const int STEPPER_DATA = 0x72; // control a stepper motor
+static const int ONEWIRE_DATA = 0x73; // send an OneWire read/write/reset/select/skip/search request
+static const int SHIFT_DATA = 0x75; // a bitstream to/from a shift register
+static const int I2C_REQUEST = 0x76; // send an I2C read/write request
+static const int I2C_REPLY = 0x77; // a reply to an I2C read request
+static const int I2C_CONFIG = 0x78; // config I2C settings such as delay times and power pins
+static const int REPORT_FIRMWARE = 0x79; // report name and version of the firmware
+static const int EXTENDED_ANALOG = 0x6F; // analog write (PWM, Servo, etc) to any pin
+static const int PIN_STATE_QUERY = 0x6D; // ask for a pin's current mode and value
+static const int PIN_STATE_RESPONSE = 0x6E; // reply with pin's current mode and value
+static const int CAPABILITY_QUERY = 0x6B; // ask for supported modes and resolution of all pins
+static const int CAPABILITY_RESPONSE = 0x6C; // reply with supported modes and resolution
+static const int ANALOG_MAPPING_QUERY = 0x69; // ask for mapping of analog to pin numbers
+static const int ANALOG_MAPPING_RESPONSE = 0x6A; // reply with mapping info
+static const int SAMPLING_INTERVAL = 0x7A; // set the poll rate of the main loop
+static const int SCHEDULER_DATA = 0x7B; // send a createtask/deletetask/addtotask/schedule/querytasks/querytask request to the scheduler
+static const int SYSEX_NON_REALTIME = 0x7E; // MIDI Reserved for non-realtime messages
+static const int SYSEX_REALTIME = 0x7F; // MIDI Reserved for realtime messages
+
+// pin modes
+static const int PIN_MODE_INPUT = 0x00; // same as INPUT defined in Arduino.h
+static const int PIN_MODE_OUTPUT = 0x01; // same as OUTPUT defined in Arduino.h
+static const int PIN_MODE_ANALOG = 0x02; // analog pin in analogInput mode
+static const int PIN_MODE_PWM = 0x03; // digital pin in PWM output mode
+static const int PIN_MODE_SERVO = 0x04; // digital pin in Servo output mode
+static const int PIN_MODE_SHIFT = 0x05; // shiftIn/shiftOut mode
+static const int PIN_MODE_I2C = 0x06; // pin included in I2C setup
+static const int PIN_MODE_ONEWIRE = 0x07; // pin configured for 1-wire
+static const int PIN_MODE_STEPPER = 0x08; // pin configured for stepper motor
+static const int PIN_MODE_ENCODER = 0x09; // pin configured for rotary encoders
+static const int PIN_MODE_SERIAL = 0x0A; // pin configured for serial communication
+static const int PIN_MODE_PULLUP = 0x0B; // enable internal pull-up resistor for pin
+static const int PIN_MODE_IGNORE = 0x7F; // pin configured to be ignored by digitalWrite and capabilityResponse
+
+static const int TOTAL_PIN_MODES = 13;
+
+} // namespace firmata
+
+#endif // FirmataConstants_h
--- /dev/null
+/*
+ FirmataDefines.h
+ Copyright (c) 2006-2008 Hans-Christoph Steiner. All rights reserved.
+ Copyright (C) 2009-2016 Jeff Hoefs. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+*/
+
+#ifndef FirmataDefines_h
+#define FirmataDefines_h
+
+#include "FirmataConstants.h"
+
+/* Version numbers for the Firmata library.
+ * The firmware version will not always equal the protocol version going forward.
+ * Query using the REPORT_FIRMWARE message.
+ */
+#define FIRMATA_FIRMWARE_MAJOR_VERSION firmata::FIRMWARE_MAJOR_VERSION
+#define FIRMATA_FIRMWARE_MINOR_VERSION firmata::FIRMWARE_MINOR_VERSION
+#define FIRMATA_FIRMWARE_BUGFIX_VERSION firmata::FIRMWARE_BUGFIX_VERSION
+
+/* Version numbers for the protocol. The protocol is still changing, so these
+ * version numbers are important.
+ * Query using the REPORT_VERSION message.
+ */
+#define FIRMATA_PROTOCOL_MAJOR_VERSION firmata::PROTOCOL_MAJOR_VERSION // for non-compatible changes
+#define FIRMATA_PROTOCOL_MINOR_VERSION firmata::PROTOCOL_MINOR_VERSION // for backwards compatible changes
+#define FIRMATA_PROTOCOL_BUGFIX_VERSION firmata::PROTOCOL_BUGFIX_VERSION // for bugfix releases
+
+#ifdef MAX_DATA_BYTES
+#undef MAX_DATA_BYTES
+#endif
+#define MAX_DATA_BYTES firmata::MAX_DATA_BYTES // max number of data bytes in incoming messages
+
+// message command bytes (128-255/0x80-0xFF)
+
+#ifdef DIGITAL_MESSAGE
+#undef DIGITAL_MESSAGE
+#endif
+#define DIGITAL_MESSAGE firmata::DIGITAL_MESSAGE // send data for a digital port (collection of 8 pins)
+
+#ifdef ANALOG_MESSAGE
+#undef ANALOG_MESSAGE
+#endif
+#define ANALOG_MESSAGE firmata::ANALOG_MESSAGE // send data for an analog pin (or PWM)
+
+#ifdef REPORT_ANALOG
+#undef REPORT_ANALOG
+#endif
+#define REPORT_ANALOG firmata::REPORT_ANALOG // enable analog input by pin #
+
+#ifdef REPORT_DIGITAL
+#undef REPORT_DIGITAL
+#endif
+#define REPORT_DIGITAL firmata::REPORT_DIGITAL // enable digital input by port pair
+
+//
+
+#ifdef SET_PIN_MODE
+#undef SET_PIN_MODE
+#endif
+#define SET_PIN_MODE firmata::SET_PIN_MODE // set a pin to INPUT/OUTPUT/PWM/etc
+
+#ifdef SET_DIGITAL_PIN_VALUE
+#undef SET_DIGITAL_PIN_VALUE
+#endif
+#define SET_DIGITAL_PIN_VALUE firmata::SET_DIGITAL_PIN_VALUE // set value of an individual digital pin
+
+//
+
+#ifdef REPORT_VERSION
+#undef REPORT_VERSION
+#endif
+#define REPORT_VERSION firmata::REPORT_VERSION // report protocol version
+
+#ifdef SYSTEM_RESET
+#undef SYSTEM_RESET
+#endif
+#define SYSTEM_RESET firmata::SYSTEM_RESET // reset from MIDI
+
+//
+
+#ifdef START_SYSEX
+#undef START_SYSEX
+#endif
+#define START_SYSEX firmata::START_SYSEX // start a MIDI Sysex message
+
+#ifdef END_SYSEX
+#undef END_SYSEX
+#endif
+#define END_SYSEX firmata::END_SYSEX // end a MIDI Sysex message
+
+// extended command set using sysex (0-127/0x00-0x7F)
+/* 0x00-0x0F reserved for user-defined commands */
+
+#ifdef SERIAL_MESSAGE
+#undef SERIAL_MESSAGE
+#endif
+#define SERIAL_MESSAGE firmata::SERIAL_DATA // communicate with serial devices, including other boards
+
+#ifdef ENCODER_DATA
+#undef ENCODER_DATA
+#endif
+#define ENCODER_DATA firmata::ENCODER_DATA // reply with encoders current positions
+
+#ifdef SERVO_CONFIG
+#undef SERVO_CONFIG
+#endif
+#define SERVO_CONFIG firmata::SERVO_CONFIG // set max angle, minPulse, maxPulse, freq
+
+#ifdef STRING_DATA
+#undef STRING_DATA
+#endif
+#define STRING_DATA firmata::STRING_DATA // a string message with 14-bits per char
+
+#ifdef STEPPER_DATA
+#undef STEPPER_DATA
+#endif
+#define STEPPER_DATA firmata::STEPPER_DATA // control a stepper motor
+
+#ifdef ONEWIRE_DATA
+#undef ONEWIRE_DATA
+#endif
+#define ONEWIRE_DATA firmata::ONEWIRE_DATA // send an OneWire read/write/reset/select/skip/search request
+
+#ifdef SHIFT_DATA
+#undef SHIFT_DATA
+#endif
+#define SHIFT_DATA firmata::SHIFT_DATA // a bitstream to/from a shift register
+
+#ifdef I2C_REQUEST
+#undef I2C_REQUEST
+#endif
+#define I2C_REQUEST firmata::I2C_REQUEST // send an I2C read/write request
+
+#ifdef I2C_REPLY
+#undef I2C_REPLY
+#endif
+#define I2C_REPLY firmata::I2C_REPLY // a reply to an I2C read request
+
+#ifdef I2C_CONFIG
+#undef I2C_CONFIG
+#endif
+#define I2C_CONFIG firmata::I2C_CONFIG // config I2C settings such as delay times and power pins
+
+#ifdef REPORT_FIRMWARE
+#undef REPORT_FIRMWARE
+#endif
+#define REPORT_FIRMWARE firmata::REPORT_FIRMWARE // report name and version of the firmware
+
+#ifdef EXTENDED_ANALOG
+#undef EXTENDED_ANALOG
+#endif
+#define EXTENDED_ANALOG firmata::EXTENDED_ANALOG // analog write (PWM, Servo, etc) to any pin
+
+#ifdef PIN_STATE_QUERY
+#undef PIN_STATE_QUERY
+#endif
+#define PIN_STATE_QUERY firmata::PIN_STATE_QUERY // ask for a pin's current mode and value
+
+#ifdef PIN_STATE_RESPONSE
+#undef PIN_STATE_RESPONSE
+#endif
+#define PIN_STATE_RESPONSE firmata::PIN_STATE_RESPONSE // reply with pin's current mode and value
+
+#ifdef CAPABILITY_QUERY
+#undef CAPABILITY_QUERY
+#endif
+#define CAPABILITY_QUERY firmata::CAPABILITY_QUERY // ask for supported modes and resolution of all pins
+
+#ifdef CAPABILITY_RESPONSE
+#undef CAPABILITY_RESPONSE
+#endif
+#define CAPABILITY_RESPONSE firmata::CAPABILITY_RESPONSE // reply with supported modes and resolution
+
+#ifdef ANALOG_MAPPING_QUERY
+#undef ANALOG_MAPPING_QUERY
+#endif
+#define ANALOG_MAPPING_QUERY firmata::ANALOG_MAPPING_QUERY // ask for mapping of analog to pin numbers
+
+#ifdef ANALOG_MAPPING_RESPONSE
+#undef ANALOG_MAPPING_RESPONSE
+#endif
+#define ANALOG_MAPPING_RESPONSE firmata::ANALOG_MAPPING_RESPONSE // reply with mapping info
+
+#ifdef SAMPLING_INTERVAL
+#undef SAMPLING_INTERVAL
+#endif
+#define SAMPLING_INTERVAL firmata::SAMPLING_INTERVAL // set the poll rate of the main loop
+
+#ifdef SCHEDULER_DATA
+#undef SCHEDULER_DATA
+#endif
+#define SCHEDULER_DATA firmata::SCHEDULER_DATA // send a createtask/deletetask/addtotask/schedule/querytasks/querytask request to the scheduler
+
+#ifdef SYSEX_NON_REALTIME
+#undef SYSEX_NON_REALTIME
+#endif
+#define SYSEX_NON_REALTIME firmata::SYSEX_NON_REALTIME // MIDI Reserved for non-realtime messages
+
+#ifdef SYSEX_REALTIME
+#undef SYSEX_REALTIME
+#endif
+#define SYSEX_REALTIME firmata::SYSEX_REALTIME // MIDI Reserved for realtime messages
+
+// pin modes
+
+#ifdef PIN_MODE_INPUT
+#undef PIN_MODE_INPUT
+#endif
+#define PIN_MODE_INPUT firmata::PIN_MODE_INPUT // same as INPUT defined in Arduino.h
+
+#ifdef PIN_MODE_OUTPUT
+#undef PIN_MODE_OUTPUT
+#endif
+#define PIN_MODE_OUTPUT firmata::PIN_MODE_OUTPUT // same as OUTPUT defined in Arduino.h
+
+#ifdef PIN_MODE_ANALOG
+#undef PIN_MODE_ANALOG
+#endif
+#define PIN_MODE_ANALOG firmata::PIN_MODE_ANALOG // analog pin in analogInput mode
+
+#ifdef PIN_MODE_PWM
+#undef PIN_MODE_PWM
+#endif
+#define PIN_MODE_PWM firmata::PIN_MODE_PWM // digital pin in PWM output mode
+
+#ifdef PIN_MODE_SERVO
+#undef PIN_MODE_SERVO
+#endif
+#define PIN_MODE_SERVO firmata::PIN_MODE_SERVO // digital pin in Servo output mode
+
+#ifdef PIN_MODE_SHIFT
+#undef PIN_MODE_SHIFT
+#endif
+#define PIN_MODE_SHIFT firmata::PIN_MODE_SHIFT // shiftIn/shiftOut mode
+
+#ifdef PIN_MODE_I2C
+#undef PIN_MODE_I2C
+#endif
+#define PIN_MODE_I2C firmata::PIN_MODE_I2C // pin included in I2C setup
+
+#ifdef PIN_MODE_ONEWIRE
+#undef PIN_MODE_ONEWIRE
+#endif
+#define PIN_MODE_ONEWIRE firmata::PIN_MODE_ONEWIRE // pin configured for 1-wire
+
+#ifdef PIN_MODE_STEPPER
+#undef PIN_MODE_STEPPER
+#endif
+#define PIN_MODE_STEPPER firmata::PIN_MODE_STEPPER // pin configured for stepper motor
+
+#ifdef PIN_MODE_ENCODER
+#undef PIN_MODE_ENCODER
+#endif
+#define PIN_MODE_ENCODER firmata::PIN_MODE_ENCODER // pin configured for rotary encoders
+
+#ifdef PIN_MODE_SERIAL
+#undef PIN_MODE_SERIAL
+#endif
+#define PIN_MODE_SERIAL firmata::PIN_MODE_SERIAL // pin configured for serial communication
+
+#ifdef PIN_MODE_PULLUP
+#undef PIN_MODE_PULLUP
+#endif
+#define PIN_MODE_PULLUP firmata::PIN_MODE_PULLUP // enable internal pull-up resistor for pin
+
+#ifdef PIN_MODE_IGNORE
+#undef PIN_MODE_IGNORE
+#endif
+#define PIN_MODE_IGNORE firmata::PIN_MODE_IGNORE // pin configured to be ignored by digitalWrite and capabilityResponse
+
+#ifdef TOTAL_PIN_MODES
+#undef TOTAL_PIN_MODES
+#endif
+#define TOTAL_PIN_MODES firmata::TOTAL_PIN_MODES
+
+#endif // FirmataConstants_h
--- /dev/null
+/*
+ FirmataMarshaller.cpp
+ Copyright (c) 2006-2008 Hans-Christoph Steiner. All rights reserved.
+ Copyright (C) 2009-2016 Jeff Hoefs. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+*/
+
+//******************************************************************************
+//* Includes
+//******************************************************************************
+
+#include "FirmataMarshaller.h"
+
+#if defined(__cplusplus) && !defined(ARDUINO)
+ #include <cstring>
+#else
+ #include <string.h>
+#endif
+
+#include "FirmataConstants.h"
+
+using namespace firmata;
+
+//******************************************************************************
+//* Support Functions
+//******************************************************************************
+
+/**
+ * Request or halt a stream of analog readings from the Firmata host application. The range of pins is
+ * limited to [0..15] when using the REPORT_ANALOG. The maximum result of the REPORT_ANALOG is limited to 14 bits
+ * (16384). To increase the pin range or value, see the documentation for the EXTENDED_ANALOG
+ * message.
+ * @param pin The analog pin for which to request the value (limited to pins 0 - 15).
+ * @param stream_enable A zero value will disable the stream, a non-zero will enable the stream
+ * @note The maximum resulting value is 14-bits (16384).
+ */
+void FirmataMarshaller::reportAnalog(uint8_t pin, bool stream_enable)
+const
+{
+ if ( (Stream *)NULL == FirmataStream ) { return; }
+ // pin can only be 0-15, so chop higher bits
+ FirmataStream->write(REPORT_ANALOG | (pin & 0xF));
+ FirmataStream->write(stream_enable);
+}
+
+/**
+ * Request or halt an 8-bit port stream from the Firmata host application (protocol v2 and later).
+ * Send 14-bits in a single digital message (protocol v1).
+ * @param portNumber The port number for which to request the value. Note that this is not the same as a "port" on the
+ * physical microcontroller. Ports are defined in order per every 8 pins in ascending order
+ * of the Arduino digital pin numbering scheme. Port 0 = pins D0 - D7, port 1 = pins D8 - D15, etc.
+ * @param stream_enable A zero value will disable the stream, a non-zero will enable the stream
+ */
+void FirmataMarshaller::reportDigitalPort(uint8_t portNumber, bool stream_enable)
+const
+{
+ if ( (Stream *)NULL == FirmataStream ) { return; }
+ FirmataStream->write(REPORT_DIGITAL | (portNumber & 0xF));
+ FirmataStream->write(stream_enable);
+}
+
+/**
+ * An alternative to the normal analog message, this extended version allows addressing beyond
+ * pin 15 and supports sending analog values with any number of bits.
+ * @param pin The analog pin to which the value is sent.
+ * @param bytec The size of the storage for the analog value
+ * @param bytev The pointer to the location of the analog value
+ */
+void FirmataMarshaller::sendExtendedAnalog(uint8_t pin, size_t bytec, uint8_t * bytev)
+const
+{
+ if ( (Stream *)NULL == FirmataStream ) { return; }
+ FirmataStream->write(START_SYSEX);
+ FirmataStream->write(EXTENDED_ANALOG);
+ FirmataStream->write(pin);
+ encodeByteStream(bytec, bytev, bytec);
+ FirmataStream->write(END_SYSEX);
+}
+
+/**
+ * Transform 8-bit stream into 7-bit message
+ * @param bytec The number of data bytes in the message.
+ * @param bytev A pointer to the array of data bytes to send in the message.
+ * @param max_bytes Force message to be n bytes, regardless of data bits.
+ */
+void FirmataMarshaller::encodeByteStream (size_t bytec, uint8_t * bytev, size_t max_bytes)
+const
+{
+ static const size_t transmit_bits = 7;
+ static const uint8_t transmit_mask = ((1 << transmit_bits) - 1);
+
+ size_t bytes_sent = 0;
+ size_t outstanding_bits = 0;
+ uint8_t outstanding_bit_cache = *bytev;
+
+ if ( !max_bytes ) { max_bytes = static_cast<size_t>(-1); }
+ for (size_t i = 0 ; (i < bytec) && (bytes_sent < max_bytes) ; ++i) {
+ uint8_t transmit_byte = (outstanding_bit_cache|(bytev[i] << outstanding_bits));
+ FirmataStream->write(transmit_mask & transmit_byte);
+ ++bytes_sent;
+ outstanding_bit_cache = (bytev[i] >> (transmit_bits - outstanding_bits));
+ outstanding_bits = (outstanding_bits + (8 - transmit_bits));
+ for ( ; (outstanding_bits >= transmit_bits) && (bytes_sent < max_bytes) ; ) {
+ transmit_byte = outstanding_bit_cache;
+ FirmataStream->write(transmit_mask & transmit_byte);
+ ++bytes_sent;
+ outstanding_bit_cache >>= transmit_bits;
+ outstanding_bits -= transmit_bits;
+ }
+ }
+ if ( outstanding_bits && (bytes_sent < max_bytes) ) {
+ FirmataStream->write(static_cast<uint8_t>((1 << outstanding_bits) - 1) & outstanding_bit_cache);
+ }
+}
+
+//******************************************************************************
+//* Constructors
+//******************************************************************************
+
+/**
+ * The FirmataMarshaller class.
+ */
+FirmataMarshaller::FirmataMarshaller()
+:
+ FirmataStream((Stream *)NULL)
+{
+}
+
+//******************************************************************************
+//* Public Methods
+//******************************************************************************
+
+/**
+ * Reassign the Firmata stream transport.
+ * @param s A reference to the Stream transport object. This can be any type of
+ * transport that implements the Stream interface. Some examples include Ethernet, WiFi
+ * and other UARTs on the board (Serial1, Serial2, etc).
+ */
+void FirmataMarshaller::begin(Stream &s)
+{
+ FirmataStream = &s;
+}
+
+/**
+ * Closes the FirmataMarshaller stream by setting its stream reference to `(Stream *)NULL`
+ */
+void FirmataMarshaller::end(void)
+{
+ FirmataStream = (Stream *)NULL;
+}
+
+//******************************************************************************
+//* Output Stream Handling
+//******************************************************************************
+
+/**
+ * Query the target's firmware name and version
+ */
+void FirmataMarshaller::queryFirmwareVersion(void)
+const
+{
+ if ( (Stream *)NULL == FirmataStream ) { return; }
+ FirmataStream->write(START_SYSEX);
+ FirmataStream->write(REPORT_FIRMWARE);
+ FirmataStream->write(END_SYSEX);
+}
+
+/**
+ * Query the target's Firmata protocol version
+ */
+void FirmataMarshaller::queryVersion(void)
+const
+{
+ if ( (Stream *)NULL == FirmataStream ) { return; }
+ FirmataStream->write(REPORT_VERSION);
+}
+
+/**
+ * Halt the stream of analog readings from the Firmata host application. The range of pins is
+ * limited to [0..15] when using the REPORT_ANALOG. The maximum result of the REPORT_ANALOG is limited to 14 bits
+ * (16384). To increase the pin range or value, see the documentation for the EXTENDED_ANALOG
+ * message.
+ * @param pin The analog pin for which to request the value (limited to pins 0 - 15).
+ */
+void FirmataMarshaller::reportAnalogDisable(uint8_t pin)
+const
+{
+ reportAnalog(pin, false);
+}
+
+/**
+ * Request a stream of analog readings from the Firmata host application. The range of pins is
+ * limited to [0..15] when using the REPORT_ANALOG. The maximum result of the REPORT_ANALOG is limited to 14 bits
+ * (16384). To increase the pin range or value, see the documentation for the EXTENDED_ANALOG
+ * message.
+ * @param pin The analog pin for which to request the value (limited to pins 0 - 15).
+ */
+void FirmataMarshaller::reportAnalogEnable(uint8_t pin)
+const
+{
+ reportAnalog(pin, true);
+}
+
+/**
+ * Halt an 8-bit port stream from the Firmata host application (protocol v2 and later).
+ * Send 14-bits in a single digital message (protocol v1).
+ * @param portNumber The port number for which to request the value. Note that this is not the same as a "port" on the
+ * physical microcontroller. Ports are defined in order per every 8 pins in ascending order
+ * of the Arduino digital pin numbering scheme. Port 0 = pins D0 - D7, port 1 = pins D8 - D15, etc.
+ */
+void FirmataMarshaller::reportDigitalPortDisable(uint8_t portNumber)
+const
+{
+ reportDigitalPort(portNumber, false);
+}
+
+/**
+ * Request an 8-bit port stream from the Firmata host application (protocol v2 and later).
+ * Send 14-bits in a single digital message (protocol v1).
+ * @param portNumber The port number for which to request the value. Note that this is not the same as a "port" on the
+ * physical microcontroller. Ports are defined in order per every 8 pins in ascending order
+ * of the Arduino digital pin numbering scheme. Port 0 = pins D0 - D7, port 1 = pins D8 - D15, etc.
+ */
+void FirmataMarshaller::reportDigitalPortEnable(uint8_t portNumber)
+const
+{
+ reportDigitalPort(portNumber, true);
+}
+
+/**
+ * Send an analog message to the Firmata host application. The range of pins is limited to [0..15]
+ * when using the ANALOG_MESSAGE. The maximum value of the ANALOG_MESSAGE is limited to 14 bits
+ * (16384). To increase the pin range or value, see the documentation for the EXTENDED_ANALOG
+ * message.
+ * @param pin The analog pin to which the value is sent.
+ * @param value The value of the analog pin (0 - 1024 for 10-bit analog, 0 - 4096 for 12-bit, etc).
+ * @note The maximum value is 14-bits (16384).
+ */
+void FirmataMarshaller::sendAnalog(uint8_t pin, uint16_t value)
+const
+{
+ if ( (Stream *)NULL == FirmataStream ) { return; }
+ if ( (0xF >= pin) && (0x3FFF >= value) ) {
+ FirmataStream->write(ANALOG_MESSAGE|pin);
+ encodeByteStream(sizeof(value), reinterpret_cast<uint8_t *>(&value), sizeof(value));
+ } else {
+ sendExtendedAnalog(pin, sizeof(value), reinterpret_cast<uint8_t *>(&value));
+ }
+}
+
+/**
+ * Send an analog mapping query to the Firmata host application. The resulting sysex message will
+ * have an ANALOG_MAPPING_RESPONSE command byte, followed by a list of pins [0-n]; where each
+ * pin will specify its corresponding analog pin number or 0x7F (127) if not applicable.
+ */
+void FirmataMarshaller::sendAnalogMappingQuery(void)
+const
+{
+ sendSysex(ANALOG_MAPPING_QUERY, 0, NULL);
+}
+
+/**
+ * Send a capability query to the Firmata host application. The resulting sysex message will have
+ * a CAPABILITY_RESPONSE command byte, followed by a list of byte tuples (mode and mode resolution)
+ * for each pin; where each pin list is terminated by 0x7F (127).
+ */
+void FirmataMarshaller::sendCapabilityQuery(void)
+const
+{
+ sendSysex(CAPABILITY_QUERY, 0, NULL);
+}
+
+/**
+ * Send a single digital pin value to the Firmata host application.
+ * @param pin The digital pin to send the value of.
+ * @param value The value of the pin.
+ */
+void FirmataMarshaller::sendDigital(uint8_t pin, uint8_t value)
+const
+{
+ if ( (Stream *)NULL == FirmataStream ) { return; }
+ FirmataStream->write(SET_DIGITAL_PIN_VALUE);
+ FirmataStream->write(pin & 0x7F);
+ FirmataStream->write(value != 0);
+}
+
+
+/**
+ * Send an 8-bit port in a single digital message (protocol v2 and later).
+ * Send 14-bits in a single digital message (protocol v1).
+ * @param portNumber The port number to send. Note that this is not the same as a "port" on the
+ * physical microcontroller. Ports are defined in order per every 8 pins in ascending order
+ * of the Arduino digital pin numbering scheme. Port 0 = pins D0 - D7, port 1 = pins D8 - D15, etc.
+ * @param portData The value of the port. The value of each pin in the port is represented by a bit.
+ */
+void FirmataMarshaller::sendDigitalPort(uint8_t portNumber, uint16_t portData)
+const
+{
+ if ( (Stream *)NULL == FirmataStream ) { return; }
+ FirmataStream->write(DIGITAL_MESSAGE | (portNumber & 0xF));
+ // Tx bits 0-6 (protocol v1 and higher)
+ // Tx bits 7-13 (bit 7 only for protocol v2 and higher)
+ encodeByteStream(sizeof(portData), reinterpret_cast<uint8_t *>(&portData), sizeof(portData));
+}
+
+/**
+ * Sends the firmware name and version to the Firmata host application.
+ * @param major The major verison number
+ * @param minor The minor version number
+ * @param bytec The length of the firmware name
+ * @param bytev The firmware name array
+ */
+void FirmataMarshaller::sendFirmwareVersion(uint8_t major, uint8_t minor, size_t bytec, uint8_t *bytev)
+const
+{
+ if ( (Stream *)NULL == FirmataStream ) { return; }
+ size_t i;
+ FirmataStream->write(START_SYSEX);
+ FirmataStream->write(REPORT_FIRMWARE);
+ FirmataStream->write(major);
+ FirmataStream->write(minor);
+ for (i = 0; i < bytec; ++i) {
+ encodeByteStream(sizeof(bytev[i]), reinterpret_cast<uint8_t *>(&bytev[i]));
+ }
+ FirmataStream->write(END_SYSEX);
+}
+
+/**
+ * Send the Firmata protocol version to the Firmata host application.
+ * @param major The major verison number
+ * @param minor The minor version number
+ */
+void FirmataMarshaller::sendVersion(uint8_t major, uint8_t minor)
+const
+{
+ if ( (Stream *)NULL == FirmataStream ) { return; }
+ FirmataStream->write(REPORT_VERSION);
+ FirmataStream->write(major);
+ FirmataStream->write(minor);
+}
+
+/**
+ * Send the pin mode/configuration. The pin configuration (or mode) in Firmata represents the
+ * current function of the pin. Examples are digital input or output, analog input, pwm, i2c,
+ * serial (uart), etc.
+ * @param pin The pin to configure.
+ * @param config The configuration value for the specified pin.
+ */
+void FirmataMarshaller::sendPinMode(uint8_t pin, uint8_t config)
+const
+{
+ if ( (Stream *)NULL == FirmataStream ) { return; }
+ FirmataStream->write(SET_PIN_MODE);
+ FirmataStream->write(pin);
+ FirmataStream->write(config);
+}
+
+/**
+ * Send a pin state query to the Firmata host application. The resulting sysex message will have
+ * a PIN_STATE_RESPONSE command byte, followed by the pin number, the pin mode and a stream of
+ * bits to indicate any *data* written to the pin (pin state).
+ * @param pin The pin to query
+ * @note The pin state is any data written to the pin (i.e. pin state != pin value)
+ */
+void FirmataMarshaller::sendPinStateQuery(uint8_t pin)
+const
+{
+ if ( (Stream *)NULL == FirmataStream ) { return; }
+ FirmataStream->write(START_SYSEX);
+ FirmataStream->write(PIN_STATE_QUERY);
+ FirmataStream->write(pin);
+ FirmataStream->write(END_SYSEX);
+}
+
+/**
+ * Send a sysex message where all values after the command byte are packet as 2 7-bit bytes
+ * (this is not always the case so this function is not always used to send sysex messages).
+ * @param command The sysex command byte.
+ * @param bytec The number of data bytes in the message (excludes start, command and end bytes).
+ * @param bytev A pointer to the array of data bytes to send in the message.
+ */
+void FirmataMarshaller::sendSysex(uint8_t command, size_t bytec, uint8_t *bytev)
+const
+{
+ if ( (Stream *)NULL == FirmataStream ) { return; }
+ size_t i;
+ FirmataStream->write(START_SYSEX);
+ FirmataStream->write(command);
+ for (i = 0; i < bytec; ++i) {
+ encodeByteStream(sizeof(bytev[i]), reinterpret_cast<uint8_t *>(&bytev[i]));
+ }
+ FirmataStream->write(END_SYSEX);
+}
+
+/**
+ * Send a string to the Firmata host application.
+ * @param string A pointer to the char string
+ */
+void FirmataMarshaller::sendString(const char *string)
+const
+{
+ sendSysex(STRING_DATA, strlen(string), reinterpret_cast<uint8_t *>(const_cast<char *>(string)));
+}
+
+/**
+ * The sampling interval sets how often analog data and i2c data is reported to the client.
+ * @param interval_ms The interval (in milliseconds) at which to sample
+ * @note The default sampling interval is 19ms
+ */
+void FirmataMarshaller::setSamplingInterval(uint16_t interval_ms)
+const
+{
+ sendSysex(SAMPLING_INTERVAL, sizeof(interval_ms), reinterpret_cast<uint8_t *>(&interval_ms));
+}
+
+/**
+ * Perform a software reset on the target. For example, StandardFirmata.ino will initialize
+ * everything to a known state and reset the parsing buffer.
+ */
+void FirmataMarshaller::systemReset(void)
+const
+{
+ if ( (Stream *)NULL == FirmataStream ) { return; }
+ FirmataStream->write(SYSTEM_RESET);
+}
--- /dev/null
+/*
+ FirmataMarshaller.h
+ Copyright (c) 2006-2008 Hans-Christoph Steiner. All rights reserved.
+ Copyright (C) 2009-2016 Jeff Hoefs. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+*/
+
+#ifndef FirmataMarshaller_h
+#define FirmataMarshaller_h
+
+#if defined(__cplusplus) && !defined(ARDUINO)
+ #include <cstddef>
+ #include <cstdint>
+#else
+ #include <stddef.h>
+ #include <stdint.h>
+#endif
+
+#include <Stream.h>
+
+namespace firmata {
+
+class FirmataMarshaller
+{
+ friend class FirmataClass;
+
+ public:
+ /* constructors */
+ FirmataMarshaller();
+
+ /* public methods */
+ void begin(Stream &s);
+ void end();
+
+ /* serial send handling */
+ void queryFirmwareVersion(void) const;
+ void queryVersion(void) const;
+ void reportAnalogDisable(uint8_t pin) const;
+ void reportAnalogEnable(uint8_t pin) const;
+ void reportDigitalPortDisable(uint8_t portNumber) const;
+ void reportDigitalPortEnable(uint8_t portNumber) const;
+ void sendAnalog(uint8_t pin, uint16_t value) const;
+ void sendAnalogMappingQuery(void) const;
+ void sendCapabilityQuery(void) const;
+ void sendDigital(uint8_t pin, uint8_t value) const;
+ void sendDigitalPort(uint8_t portNumber, uint16_t portData) const;
+ void sendFirmwareVersion(uint8_t major, uint8_t minor, size_t bytec, uint8_t *bytev) const;
+ void sendVersion(uint8_t major, uint8_t minor) const;
+ void sendPinMode(uint8_t pin, uint8_t config) const;
+ void sendPinStateQuery(uint8_t pin) const;
+ void sendString(const char *string) const;
+ void sendSysex(uint8_t command, size_t bytec, uint8_t *bytev) const;
+ void setSamplingInterval(uint16_t interval_ms) const;
+ void systemReset(void) const;
+
+ private:
+ /* utility methods */
+ void reportAnalog(uint8_t pin, bool stream_enable) const;
+ void reportDigitalPort(uint8_t portNumber, bool stream_enable) const;
+ void sendExtendedAnalog(uint8_t pin, size_t bytec, uint8_t * bytev) const;
+ void encodeByteStream (size_t bytec, uint8_t * bytev, size_t max_bytes = 0) const;
+
+ Stream * FirmataStream;
+};
+
+} // namespace firmata
+
+#endif /* FirmataMarshaller_h */
+
--- /dev/null
+/*
+ FirmataParser.cpp
+ Copyright (c) 2006-2008 Hans-Christoph Steiner. All rights reserved.
+ Copyright (C) 2009-2016 Jeff Hoefs. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+*/
+
+//******************************************************************************
+//* Includes
+//******************************************************************************
+
+#include "FirmataParser.h"
+
+#include "FirmataConstants.h"
+
+using namespace firmata;
+
+//******************************************************************************
+//* Constructors
+//******************************************************************************
+
+/**
+ * The FirmataParser class.
+ * @param dataBuffer A pointer to an external buffer used to store parsed data
+ * @param dataBufferSize The size of the external buffer
+ */
+FirmataParser::FirmataParser(uint8_t * const dataBuffer, size_t dataBufferSize)
+:
+ dataBuffer(dataBuffer),
+ dataBufferSize(dataBufferSize),
+ executeMultiByteCommand(0),
+ multiByteChannel(0),
+ waitForData(0),
+ parsingSysex(false),
+ sysexBytesRead(0),
+ currentAnalogCallbackContext((void *)NULL),
+ currentDigitalCallbackContext((void *)NULL),
+ currentReportAnalogCallbackContext((void *)NULL),
+ currentReportDigitalCallbackContext((void *)NULL),
+ currentPinModeCallbackContext((void *)NULL),
+ currentPinValueCallbackContext((void *)NULL),
+ currentReportFirmwareCallbackContext((void *)NULL),
+ currentReportVersionCallbackContext((void *)NULL),
+ currentDataBufferOverflowCallbackContext((void *)NULL),
+ currentStringCallbackContext((void *)NULL),
+ currentSysexCallbackContext((void *)NULL),
+ currentSystemResetCallbackContext((void *)NULL),
+ currentAnalogCallback((callbackFunction)NULL),
+ currentDigitalCallback((callbackFunction)NULL),
+ currentReportAnalogCallback((callbackFunction)NULL),
+ currentReportDigitalCallback((callbackFunction)NULL),
+ currentPinModeCallback((callbackFunction)NULL),
+ currentPinValueCallback((callbackFunction)NULL),
+ currentDataBufferOverflowCallback((dataBufferOverflowCallbackFunction)NULL),
+ currentStringCallback((stringCallbackFunction)NULL),
+ currentSysexCallback((sysexCallbackFunction)NULL),
+ currentReportFirmwareCallback((versionCallbackFunction)NULL),
+ currentReportVersionCallback((systemCallbackFunction)NULL),
+ currentSystemResetCallback((systemCallbackFunction)NULL)
+{
+ allowBufferUpdate = ((uint8_t *)NULL == dataBuffer);
+}
+
+//******************************************************************************
+//* Public Methods
+//******************************************************************************
+
+//------------------------------------------------------------------------------
+// Serial Receive Handling
+
+/**
+ * Parse data from the input stream.
+ * @param inputData A single byte to be added to the parser.
+ */
+void FirmataParser::parse(uint8_t inputData)
+{
+ uint8_t command;
+
+ if (parsingSysex) {
+ if (inputData == END_SYSEX) {
+ //stop sysex byte
+ parsingSysex = false;
+ //fire off handler function
+ processSysexMessage();
+ } else {
+ //normal data byte - add to buffer
+ bufferDataAtPosition(inputData, sysexBytesRead);
+ ++sysexBytesRead;
+ }
+ } else if ( (waitForData > 0) && (inputData < 128) ) {
+ --waitForData;
+ bufferDataAtPosition(inputData, waitForData);
+ if ( (waitForData == 0) && executeMultiByteCommand ) { // got the whole message
+ switch (executeMultiByteCommand) {
+ case ANALOG_MESSAGE:
+ if (currentAnalogCallback) {
+ (*currentAnalogCallback)(currentAnalogCallbackContext,
+ multiByteChannel,
+ (dataBuffer[0] << 7)
+ + dataBuffer[1]);
+ }
+ break;
+ case DIGITAL_MESSAGE:
+ if (currentDigitalCallback) {
+ (*currentDigitalCallback)(currentDigitalCallbackContext,
+ multiByteChannel,
+ (dataBuffer[0] << 7)
+ + dataBuffer[1]);
+ }
+ break;
+ case SET_PIN_MODE:
+ if (currentPinModeCallback)
+ (*currentPinModeCallback)(currentPinModeCallbackContext, dataBuffer[1], dataBuffer[0]);
+ break;
+ case SET_DIGITAL_PIN_VALUE:
+ if (currentPinValueCallback)
+ (*currentPinValueCallback)(currentPinValueCallbackContext, dataBuffer[1], dataBuffer[0]);
+ break;
+ case REPORT_ANALOG:
+ if (currentReportAnalogCallback)
+ (*currentReportAnalogCallback)(currentReportAnalogCallbackContext, multiByteChannel, dataBuffer[0]);
+ break;
+ case REPORT_DIGITAL:
+ if (currentReportDigitalCallback)
+ (*currentReportDigitalCallback)(currentReportDigitalCallbackContext, multiByteChannel, dataBuffer[0]);
+ break;
+ }
+ executeMultiByteCommand = 0;
+ }
+ } else {
+ // remove channel info from command byte if less than 0xF0
+ if (inputData < 0xF0) {
+ command = inputData & 0xF0;
+ multiByteChannel = inputData & 0x0F;
+ } else {
+ command = inputData;
+ // commands in the 0xF* range don't use channel data
+ }
+ switch (command) {
+ case ANALOG_MESSAGE:
+ case DIGITAL_MESSAGE:
+ case SET_PIN_MODE:
+ case SET_DIGITAL_PIN_VALUE:
+ waitForData = 2; // two data bytes needed
+ executeMultiByteCommand = command;
+ break;
+ case REPORT_ANALOG:
+ case REPORT_DIGITAL:
+ waitForData = 1; // one data byte needed
+ executeMultiByteCommand = command;
+ break;
+ case START_SYSEX:
+ parsingSysex = true;
+ sysexBytesRead = 0;
+ break;
+ case SYSTEM_RESET:
+ systemReset();
+ break;
+ case REPORT_VERSION:
+ if (currentReportVersionCallback)
+ (*currentReportVersionCallback)(currentReportVersionCallbackContext);
+ break;
+ }
+ }
+}
+
+/**
+ * @return Returns true if the parser is actively parsing data.
+ */
+bool FirmataParser::isParsingMessage(void)
+const
+{
+ return (waitForData > 0 || parsingSysex);
+}
+
+/**
+ * Provides a mechanism to either set or update the working buffer of the parser.
+ * The method will be enabled when no buffer has been provided, or an overflow
+ * condition exists.
+ * @param dataBuffer A pointer to an external buffer used to store parsed data
+ * @param dataBufferSize The size of the external buffer
+ */
+int FirmataParser::setDataBufferOfSize(uint8_t * dataBuffer, size_t dataBufferSize)
+{
+ int result;
+
+ if ( !allowBufferUpdate ) {
+ result = __LINE__;
+ } else if ((uint8_t *)NULL == dataBuffer) {
+ result = __LINE__;
+ } else {
+ this->dataBuffer = dataBuffer;
+ this->dataBufferSize = dataBufferSize;
+ allowBufferUpdate = false;
+ result = 0;
+ }
+
+ return result;
+}
+
+/**
+ * Attach a generic sysex callback function to a command (options are: ANALOG_MESSAGE,
+ * DIGITAL_MESSAGE, REPORT_ANALOG, REPORT DIGITAL, SET_PIN_MODE and SET_DIGITAL_PIN_VALUE).
+ * @param command The ID of the command to attach a callback function to.
+ * @param newFunction A reference to the callback function to attach.
+ * @param context An optional context to be provided to the callback function (NULL by default).
+ * @note The context parameter is provided so you can pass a parameter, by reference, to
+ * your callback function.
+ */
+void FirmataParser::attach(uint8_t command, callbackFunction newFunction, void * context)
+{
+ switch (command) {
+ case ANALOG_MESSAGE:
+ currentAnalogCallback = newFunction;
+ currentAnalogCallbackContext = context;
+ break;
+ case DIGITAL_MESSAGE:
+ currentDigitalCallback = newFunction;
+ currentDigitalCallbackContext = context;
+ break;
+ case REPORT_ANALOG:
+ currentReportAnalogCallback = newFunction;
+ currentReportAnalogCallbackContext = context;
+ break;
+ case REPORT_DIGITAL:
+ currentReportDigitalCallback = newFunction;
+ currentReportDigitalCallbackContext = context;
+ break;
+ case SET_PIN_MODE:
+ currentPinModeCallback = newFunction;
+ currentPinModeCallbackContext = context;
+ break;
+ case SET_DIGITAL_PIN_VALUE:
+ currentPinValueCallback = newFunction;
+ currentPinValueCallbackContext = context;
+ break;
+ }
+}
+
+/**
+ * Attach a version callback function (supported option: REPORT_FIRMWARE).
+ * @param command The ID of the command to attach a callback function to.
+ * @param newFunction A reference to the callback function to attach.
+ * @param context An optional context to be provided to the callback function (NULL by default).
+ * @note The context parameter is provided so you can pass a parameter, by reference, to
+ * your callback function.
+ */
+void FirmataParser::attach(uint8_t command, versionCallbackFunction newFunction, void * context)
+{
+ switch (command) {
+ case REPORT_FIRMWARE:
+ currentReportFirmwareCallback = newFunction;
+ currentReportFirmwareCallbackContext = context;
+ break;
+ }
+}
+
+/**
+ * Attach a system callback function (supported options are: SYSTEM_RESET, REPORT_VERSION).
+ * @param command The ID of the command to attach a callback function to.
+ * @param newFunction A reference to the callback function to attach.
+ * @param context An optional context to be provided to the callback function (NULL by default).
+ * @note The context parameter is provided so you can pass a parameter, by reference, to
+ * your callback function.
+ */
+void FirmataParser::attach(uint8_t command, systemCallbackFunction newFunction, void * context)
+{
+ switch (command) {
+ case REPORT_VERSION:
+ currentReportVersionCallback = newFunction;
+ currentReportVersionCallbackContext = context;
+ break;
+ case SYSTEM_RESET:
+ currentSystemResetCallback = newFunction;
+ currentSystemResetCallbackContext = context;
+ break;
+ }
+}
+
+/**
+ * Attach a callback function for the STRING_DATA command.
+ * @param command Must be set to STRING_DATA or it will be ignored.
+ * @param newFunction A reference to the string callback function to attach.
+ * @param context An optional context to be provided to the callback function (NULL by default).
+ * @note The context parameter is provided so you can pass a parameter, by reference, to
+ * your callback function.
+ */
+void FirmataParser::attach(uint8_t command, stringCallbackFunction newFunction, void * context)
+{
+ switch (command) {
+ case STRING_DATA:
+ currentStringCallback = newFunction;
+ currentStringCallbackContext = context;
+ break;
+ }
+}
+
+/**
+ * Attach a generic sysex callback function to sysex command.
+ * @param command The ID of the command to attach a callback function to.
+ * @param newFunction A reference to the sysex callback function to attach.
+ * @param context An optional context to be provided to the callback function (NULL by default).
+ * @note The context parameter is provided so you can pass a parameter, by reference, to
+ * your callback function.
+ */
+void FirmataParser::attach(uint8_t command, sysexCallbackFunction newFunction, void * context)
+{
+ (void)command;
+ currentSysexCallback = newFunction;
+ currentSysexCallbackContext = context;
+}
+
+/**
+ * Attach a buffer overflow callback
+ * @param newFunction A reference to the buffer overflow callback function to attach.
+ * @param context An optional context to be provided to the callback function (NULL by default).
+ * @note The context parameter is provided so you can pass a parameter, by reference, to
+ * your callback function.
+ */
+void FirmataParser::attach(dataBufferOverflowCallbackFunction newFunction, void * context)
+{
+ currentDataBufferOverflowCallback = newFunction;
+ currentDataBufferOverflowCallbackContext = context;
+}
+
+/**
+ * Detach a callback function for a specified command (such as SYSTEM_RESET, STRING_DATA,
+ * ANALOG_MESSAGE, DIGITAL_MESSAGE, etc).
+ * @param command The ID of the command to detatch the callback function from.
+ */
+void FirmataParser::detach(uint8_t command)
+{
+ switch (command) {
+ case REPORT_FIRMWARE:
+ attach(command, (versionCallbackFunction)NULL, NULL);
+ break;
+ case REPORT_VERSION:
+ case SYSTEM_RESET:
+ attach(command, (systemCallbackFunction)NULL, NULL);
+ break;
+ case STRING_DATA:
+ attach(command, (stringCallbackFunction)NULL, NULL);
+ break;
+ case START_SYSEX:
+ attach(command, (sysexCallbackFunction)NULL, NULL);
+ break;
+ default:
+ attach(command, (callbackFunction)NULL, NULL);
+ break;
+ }
+}
+
+/**
+ * Detach the buffer overflow callback
+ * @param <unused> Any pointer of type dataBufferOverflowCallbackFunction.
+ */
+void FirmataParser::detach(dataBufferOverflowCallbackFunction)
+{
+ currentDataBufferOverflowCallback = (dataBufferOverflowCallbackFunction)NULL;
+ currentDataBufferOverflowCallbackContext = (void *)NULL;
+}
+
+//******************************************************************************
+//* Private Methods
+//******************************************************************************
+
+/**
+ * Buffer abstraction to prevent memory corruption
+ * @param data The byte to put into the buffer
+ * @param pos The position to insert the byte into the buffer
+ * @return writeError A boolean to indicate if an error occured
+ * @private
+ */
+bool FirmataParser::bufferDataAtPosition(const uint8_t data, const size_t pos)
+{
+ bool bufferOverflow = (pos >= dataBufferSize);
+
+ // Notify of overflow condition
+ if ( bufferOverflow
+ && ((dataBufferOverflowCallbackFunction)NULL != currentDataBufferOverflowCallback) )
+ {
+ allowBufferUpdate = true;
+ currentDataBufferOverflowCallback(currentDataBufferOverflowCallbackContext);
+ // Check if overflow was resolved during callback
+ bufferOverflow = (pos >= dataBufferSize);
+ }
+
+ // Write data to buffer if no overflow condition persist
+ if ( !bufferOverflow )
+ {
+ dataBuffer[pos] = data;
+ }
+
+ return bufferOverflow;
+}
+
+/**
+ * Transform 7-bit firmata message into 8-bit stream
+ * @param bytec The encoded data byte length of the message (max: 16383).
+ * @param bytev A pointer to the encoded array of data bytes.
+ * @return The length of the decoded data.
+ * @note The conversion will be done in place on the provided buffer.
+ * @private
+ */
+size_t FirmataParser::decodeByteStream(size_t bytec, uint8_t * bytev) {
+ size_t decoded_bytes, i;
+
+ for ( i = 0, decoded_bytes = 0 ; i < bytec ; ++decoded_bytes, ++i ) {
+ bytev[decoded_bytes] = bytev[i];
+ bytev[decoded_bytes] |= (uint8_t)(bytev[++i] << 7);
+ }
+
+ return decoded_bytes;
+}
+
+/**
+ * Process incoming sysex messages. Handles REPORT_FIRMWARE and STRING_DATA internally.
+ * Calls callback function for STRING_DATA and all other sysex messages.
+ * @private
+ */
+void FirmataParser::processSysexMessage(void)
+{
+ switch (dataBuffer[0]) { //first byte in buffer is command
+ case REPORT_FIRMWARE:
+ if (currentReportFirmwareCallback) {
+ const size_t major_version_offset = 1;
+ const size_t minor_version_offset = 2;
+ const size_t string_offset = 3;
+ // Test for malformed REPORT_FIRMWARE message (used to query firmware prior to Firmata v3.0.0)
+ if ( 3 > sysexBytesRead ) {
+ (*currentReportFirmwareCallback)(currentReportFirmwareCallbackContext, 0, 0, (const char *)NULL);
+ } else {
+ const size_t end_of_string = (string_offset + decodeByteStream((sysexBytesRead - string_offset), &dataBuffer[string_offset]));
+ bufferDataAtPosition('\0', end_of_string); // NULL terminate the string
+ (*currentReportFirmwareCallback)(currentReportFirmwareCallbackContext, (size_t)dataBuffer[major_version_offset], (size_t)dataBuffer[minor_version_offset], (const char *)&dataBuffer[string_offset]);
+ }
+ }
+ break;
+ case STRING_DATA:
+ if (currentStringCallback) {
+ const size_t string_offset = 1;
+ const size_t end_of_string = (string_offset + decodeByteStream((sysexBytesRead - string_offset), &dataBuffer[string_offset]));
+ bufferDataAtPosition('\0', end_of_string); // NULL terminate the string
+ (*currentStringCallback)(currentStringCallbackContext, (const char *)&dataBuffer[string_offset]);
+ }
+ break;
+ default:
+ if (currentSysexCallback)
+ (*currentSysexCallback)(currentSysexCallbackContext, dataBuffer[0], sysexBytesRead - 1, dataBuffer + 1);
+ }
+}
+
+/**
+ * Resets the system state upon a SYSTEM_RESET message from the host software.
+ * @private
+ */
+void FirmataParser::systemReset(void)
+{
+ size_t i;
+
+ waitForData = 0; // this flag says the next serial input will be data
+ executeMultiByteCommand = 0; // execute this after getting multi-byte data
+ multiByteChannel = 0; // channel data for multiByteCommands
+
+ for (i = 0; i < dataBufferSize; ++i) {
+ dataBuffer[i] = 0;
+ }
+
+ parsingSysex = false;
+ sysexBytesRead = 0;
+
+ if (currentSystemResetCallback)
+ (*currentSystemResetCallback)(currentSystemResetCallbackContext);
+}
--- /dev/null
+/*
+ FirmataParser.h
+ Copyright (c) 2006-2008 Hans-Christoph Steiner. All rights reserved.
+ Copyright (C) 2009-2016 Jeff Hoefs. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+*/
+
+#ifndef FirmataParser_h
+#define FirmataParser_h
+
+#if defined(__cplusplus) && !defined(ARDUINO)
+ #include <cstddef>
+ #include <cstdint>
+#else
+ #include <stddef.h>
+ #include <stdint.h>
+#endif
+
+namespace firmata {
+
+class FirmataParser
+{
+ public:
+ /* callback function types */
+ typedef void (*callbackFunction)(void * context, uint8_t command, uint16_t value);
+ typedef void (*dataBufferOverflowCallbackFunction)(void * context);
+ typedef void (*stringCallbackFunction)(void * context, const char * c_str);
+ typedef void (*sysexCallbackFunction)(void * context, uint8_t command, size_t argc, uint8_t * argv);
+ typedef void (*systemCallbackFunction)(void * context);
+ typedef void (*versionCallbackFunction)(void * context, size_t sv_major, size_t sv_minor, const char * firmware);
+
+ FirmataParser(uint8_t * dataBuffer = (uint8_t *)NULL, size_t dataBufferSize = 0);
+
+ /* serial receive handling */
+ void parse(uint8_t value);
+ bool isParsingMessage(void) const;
+ int setDataBufferOfSize(uint8_t * dataBuffer, size_t dataBufferSize);
+
+ /* attach & detach callback functions to messages */
+ void attach(uint8_t command, callbackFunction newFunction, void * context = NULL);
+ void attach(dataBufferOverflowCallbackFunction newFunction, void * context = NULL);
+ void attach(uint8_t command, stringCallbackFunction newFunction, void * context = NULL);
+ void attach(uint8_t command, sysexCallbackFunction newFunction, void * context = NULL);
+ void attach(uint8_t command, systemCallbackFunction newFunction, void * context = NULL);
+ void attach(uint8_t command, versionCallbackFunction newFunction, void * context = NULL);
+ void detach(uint8_t command);
+ void detach(dataBufferOverflowCallbackFunction);
+
+ private:
+ /* input message handling */
+ bool allowBufferUpdate;
+ uint8_t * dataBuffer; // multi-byte data
+ size_t dataBufferSize;
+ uint8_t executeMultiByteCommand; // execute this after getting multi-byte data
+ uint8_t multiByteChannel; // channel data for multiByteCommands
+ size_t waitForData; // this flag says the next serial input will be data
+
+ /* sysex */
+ bool parsingSysex;
+ size_t sysexBytesRead;
+
+ /* callback context */
+ void * currentAnalogCallbackContext;
+ void * currentDigitalCallbackContext;
+ void * currentReportAnalogCallbackContext;
+ void * currentReportDigitalCallbackContext;
+ void * currentPinModeCallbackContext;
+ void * currentPinValueCallbackContext;
+ void * currentReportFirmwareCallbackContext;
+ void * currentReportVersionCallbackContext;
+ void * currentDataBufferOverflowCallbackContext;
+ void * currentStringCallbackContext;
+ void * currentSysexCallbackContext;
+ void * currentSystemResetCallbackContext;
+
+ /* callback functions */
+ callbackFunction currentAnalogCallback;
+ callbackFunction currentDigitalCallback;
+ callbackFunction currentReportAnalogCallback;
+ callbackFunction currentReportDigitalCallback;
+ callbackFunction currentPinModeCallback;
+ callbackFunction currentPinValueCallback;
+ dataBufferOverflowCallbackFunction currentDataBufferOverflowCallback;
+ stringCallbackFunction currentStringCallback;
+ sysexCallbackFunction currentSysexCallback;
+ versionCallbackFunction currentReportFirmwareCallback;
+ systemCallbackFunction currentReportVersionCallback;
+ systemCallbackFunction currentSystemResetCallback;
+
+ /* private methods ------------------------------ */
+ bool bufferDataAtPosition(const uint8_t data, const size_t pos);
+ size_t decodeByteStream(size_t bytec, uint8_t * bytev);
+ void processSysexMessage(void);
+ void systemReset(void);
+};
+
+} // firmata
+
+#endif /* FirmataParser_h */
--- /dev/null
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+\f
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
--- /dev/null
+/*
+ * Firmata is a generic protocol for communicating with microcontrollers
+ * from software on a host computer. It is intended to work with
+ * any host computer software package.
+ *
+ * To download a host software package, please click on the following link
+ * to open the download page in your default browser.
+ *
+ * http://firmata.org/wiki/Download
+ */
+
+/*
+ * This firmware reads all inputs and sends them as fast as it can. It was
+ * inspired by the ease-of-use of the Arduino2Max program.
+ *
+ * This example code is in the public domain.
+ */
+#include <Firmata.h>
+
+byte pin;
+
+int analogValue;
+int previousAnalogValues[TOTAL_ANALOG_PINS];
+
+byte portStatus[TOTAL_PORTS]; // each bit: 1=pin is digital input, 0=other/ignore
+byte previousPINs[TOTAL_PORTS];
+
+/* timer variables */
+unsigned long currentMillis; // store the current value from millis()
+unsigned long previousMillis; // for comparison with currentMillis
+/* make sure that the FTDI buffer doesn't go over 60 bytes, otherwise you
+ get long, random delays. So only read analogs every 20ms or so */
+int samplingInterval = 19; // how often to run the main loop (in ms)
+
+void sendPort(byte portNumber, byte portValue)
+{
+ portValue = portValue & portStatus[portNumber];
+ if (previousPINs[portNumber] != portValue) {
+ Firmata.sendDigitalPort(portNumber, portValue);
+ previousPINs[portNumber] = portValue;
+ }
+}
+
+void setup()
+{
+ byte i, port, status;
+
+ Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
+
+ for (pin = 0; pin < TOTAL_PINS; pin++) {
+ if IS_PIN_DIGITAL(pin) pinMode(PIN_TO_DIGITAL(pin), INPUT);
+ }
+
+ for (port = 0; port < TOTAL_PORTS; port++) {
+ status = 0;
+ for (i = 0; i < 8; i++) {
+ if (IS_PIN_DIGITAL(port * 8 + i)) status |= (1 << i);
+ }
+ portStatus[port] = status;
+ }
+
+ Firmata.begin(57600);
+}
+
+void loop()
+{
+ byte i;
+
+ for (i = 0; i < TOTAL_PORTS; i++) {
+ sendPort(i, readPort(i, 0xff));
+ }
+ /* make sure that the FTDI buffer doesn't go over 60 bytes, otherwise you
+ get long, random delays. So only read analogs every 20ms or so */
+ currentMillis = millis();
+ if (currentMillis - previousMillis > samplingInterval) {
+ previousMillis += samplingInterval;
+ while (Firmata.available()) {
+ Firmata.processInput();
+ }
+ for (pin = 0; pin < TOTAL_ANALOG_PINS; pin++) {
+ analogValue = analogRead(pin);
+ if (analogValue != previousAnalogValues[pin]) {
+ Firmata.sendAnalog(pin, analogValue);
+ previousAnalogValues[pin] = analogValue;
+ }
+ }
+ }
+}
+
+
--- /dev/null
+/*
+ * Firmata is a generic protocol for communicating with microcontrollers
+ * from software on a host computer. It is intended to work with
+ * any host computer software package.
+ *
+ * To download a host software package, please click on the following link
+ * to open the download page in your default browser.
+ *
+ * http://firmata.org/wiki/Download
+ */
+
+/* This firmware supports as many analog ports as possible, all analog inputs,
+ * four PWM outputs, and two with servo support.
+ *
+ * This example code is in the public domain.
+ */
+#include <Servo.h>
+#include <Firmata.h>
+
+/*==============================================================================
+ * GLOBAL VARIABLES
+ *============================================================================*/
+
+/* servos */
+Servo servo9, servo10; // one instance per pin
+/* analog inputs */
+int analogInputsToReport = 0; // bitwise array to store pin reporting
+int analogPin = 0; // counter for reading analog pins
+/* timer variables */
+unsigned long currentMillis; // store the current value from millis()
+unsigned long previousMillis; // for comparison with currentMillis
+
+
+/*==============================================================================
+ * FUNCTIONS
+ *============================================================================*/
+
+void analogWriteCallback(byte pin, int value)
+{
+ switch (pin) {
+ case 9: servo9.write(value); break;
+ case 10: servo10.write(value); break;
+ case 3:
+ case 5:
+ case 6:
+ case 11: // PWM pins
+ analogWrite(pin, value);
+ break;
+ }
+}
+// -----------------------------------------------------------------------------
+// sets bits in a bit array (int) to toggle the reporting of the analogIns
+void reportAnalogCallback(byte pin, int value)
+{
+ if (value == 0) {
+ analogInputsToReport = analogInputsToReport & ~ (1 << pin);
+ }
+ else { // everything but 0 enables reporting of that pin
+ analogInputsToReport = analogInputsToReport | (1 << pin);
+ }
+ // TODO: save status to EEPROM here, if changed
+}
+
+/*==============================================================================
+ * SETUP()
+ *============================================================================*/
+void setup()
+{
+ Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
+ Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
+ Firmata.attach(REPORT_ANALOG, reportAnalogCallback);
+
+ servo9.attach(9);
+ servo10.attach(10);
+ Firmata.begin(57600);
+}
+
+/*==============================================================================
+ * LOOP()
+ *============================================================================*/
+void loop()
+{
+ while (Firmata.available())
+ Firmata.processInput();
+ currentMillis = millis();
+ if (currentMillis - previousMillis > 20) {
+ previousMillis += 20; // run this every 20ms
+ for (analogPin = 0; analogPin < TOTAL_ANALOG_PINS; analogPin++) {
+ if ( analogInputsToReport & (1 << analogPin) )
+ Firmata.sendAnalog(analogPin, analogRead(analogPin));
+ }
+ }
+}
+
--- /dev/null
+/*
+ * Firmata is a generic protocol for communicating with microcontrollers
+ * from software on a host computer. It is intended to work with
+ * any host computer software package.
+ *
+ * To download a host software package, please click on the following link
+ * to open the download page in your default browser.
+ *
+ * http://firmata.org/wiki/Download
+ */
+
+/* This sketch accepts strings and raw sysex messages and echos them back.
+ *
+ * This example code is in the public domain.
+ */
+#include <Firmata.h>
+
+void stringCallback(char *myString)
+{
+ Firmata.sendString(myString);
+}
+
+
+void sysexCallback(byte command, byte argc, byte *argv)
+{
+ Firmata.sendSysex(command, argc, argv);
+}
+
+void setup()
+{
+ Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
+ Firmata.attach(STRING_DATA, stringCallback);
+ Firmata.attach(START_SYSEX, sysexCallback);
+ Firmata.begin(57600);
+}
+
+void loop()
+{
+ while (Firmata.available()) {
+ Firmata.processInput();
+ }
+}
+
+
--- /dev/null
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+\f
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
--- /dev/null
+/*
+ * Firmata is a generic protocol for communicating with microcontrollers
+ * from software on a host computer. It is intended to work with
+ * any host computer software package.
+ *
+ * To download a host software package, please click on the following link
+ * to open the download page in your default browser.
+ *
+ * http://firmata.org/wiki/Download
+ */
+
+/*
+ Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+ */
+
+/*
+ * This is an old version of StandardFirmata (v2.0). It is kept here because
+ * its the last version that works on an ATMEGA8 chip. Also, it can be used
+ * for host software that has not been updated to a newer version of the
+ * protocol. It also uses the old baud rate of 115200 rather than 57600.
+ */
+
+#include <EEPROM.h>
+#include <Firmata.h>
+
+/*==============================================================================
+ * GLOBAL VARIABLES
+ *============================================================================*/
+
+/* analog inputs */
+int analogInputsToReport = 0; // bitwise array to store pin reporting
+int analogPin = 0; // counter for reading analog pins
+
+/* digital pins */
+byte reportPINs[TOTAL_PORTS]; // PIN == input port
+byte previousPINs[TOTAL_PORTS]; // PIN == input port
+byte pinStatus[TOTAL_PINS]; // store pin status, default OUTPUT
+byte portStatus[TOTAL_PORTS];
+
+/* timer variables */
+unsigned long currentMillis; // store the current value from millis()
+unsigned long previousMillis; // for comparison with currentMillis
+
+
+/*==============================================================================
+ * FUNCTIONS
+ *============================================================================*/
+
+void outputPort(byte portNumber, byte portValue)
+{
+ portValue = portValue & ~ portStatus[portNumber];
+ if (previousPINs[portNumber] != portValue) {
+ Firmata.sendDigitalPort(portNumber, portValue);
+ previousPINs[portNumber] = portValue;
+ Firmata.sendDigitalPort(portNumber, portValue);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * check all the active digital inputs for change of state, then add any events
+ * to the Serial output queue using Serial.print() */
+void checkDigitalInputs(void)
+{
+ byte i, tmp;
+ for (i = 0; i < TOTAL_PORTS; i++) {
+ if (reportPINs[i]) {
+ switch (i) {
+ case 0: outputPort(0, PIND & ~ B00000011); break; // ignore Rx/Tx 0/1
+ case 1: outputPort(1, PINB); break;
+ case 2: outputPort(2, PINC); break;
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+/* sets the pin mode to the correct state and sets the relevant bits in the
+ * two bit-arrays that track Digital I/O and PWM status
+ */
+void setPinModeCallback(byte pin, int mode) {
+ byte port = 0;
+ byte offset = 0;
+
+ if (pin < 8) {
+ port = 0;
+ offset = 0;
+ } else if (pin < 14) {
+ port = 1;
+ offset = 8;
+ } else if (pin < 22) {
+ port = 2;
+ offset = 14;
+ }
+
+ if (pin > 1) { // ignore RxTx (pins 0 and 1)
+ pinStatus[pin] = mode;
+ switch (mode) {
+ case INPUT:
+ pinMode(pin, INPUT);
+ portStatus[port] = portStatus[port] & ~ (1 << (pin - offset));
+ break;
+ case OUTPUT:
+ digitalWrite(pin, LOW); // disable PWM
+ case PWM:
+ pinMode(pin, OUTPUT);
+ portStatus[port] = portStatus[port] | (1 << (pin - offset));
+ break;
+ //case ANALOG: // TODO figure this out
+ default:
+ Firmata.sendString("");
+ }
+ // TODO: save status to EEPROM here, if changed
+ }
+}
+
+void analogWriteCallback(byte pin, int value)
+{
+ setPinModeCallback(pin, PIN_MODE_PWM);
+ analogWrite(pin, value);
+}
+
+void digitalWriteCallback(byte port, int value)
+{
+ switch (port) {
+ case 0: // pins 2-7 (don't change Rx/Tx, pins 0 and 1)
+ // 0xFF03 == B1111111100000011 0x03 == B00000011
+ PORTD = (value & ~ 0xFF03) | (PORTD & 0x03);
+ break;
+ case 1: // pins 8-13 (14,15 are disabled for the crystal)
+ PORTB = (byte)value;
+ break;
+ case 2: // analog pins used as digital
+ PORTC = (byte)value;
+ break;
+ }
+}
+
+// -----------------------------------------------------------------------------
+/* sets bits in a bit array (int) to toggle the reporting of the analogIns
+ */
+//void FirmataClass::setAnalogPinReporting(byte pin, byte state) {
+//}
+void reportAnalogCallback(byte pin, int value)
+{
+ if (value == 0) {
+ analogInputsToReport = analogInputsToReport & ~ (1 << pin);
+ }
+ else { // everything but 0 enables reporting of that pin
+ analogInputsToReport = analogInputsToReport | (1 << pin);
+ }
+ // TODO: save status to EEPROM here, if changed
+}
+
+void reportDigitalCallback(byte port, int value)
+{
+ reportPINs[port] = (byte)value;
+ if (port == 2) // turn off analog reporting when used as digital
+ analogInputsToReport = 0;
+}
+
+/*==============================================================================
+ * SETUP()
+ *============================================================================*/
+void setup()
+{
+ byte i;
+
+ Firmata.setFirmwareVersion(2, 0);
+
+ Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
+ Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
+ Firmata.attach(REPORT_ANALOG, reportAnalogCallback);
+ Firmata.attach(REPORT_DIGITAL, reportDigitalCallback);
+ Firmata.attach(SET_PIN_MODE, setPinModeCallback);
+
+ portStatus[0] = B00000011; // ignore Tx/RX pins
+ portStatus[1] = B11000000; // ignore 14/15 pins
+ portStatus[2] = B00000000;
+
+ // for(i=0; i<TOTAL_PINS; ++i) { // TODO make this work with analogs
+ for (i = 0; i < 14; ++i) {
+ setPinModeCallback(i, OUTPUT);
+ }
+ // set all outputs to 0 to make sure internal pull-up resistors are off
+ PORTB = 0; // pins 8-15
+ PORTC = 0; // analog port
+ PORTD = 0; // pins 0-7
+
+ // TODO rethink the init, perhaps it should report analog on default
+ for (i = 0; i < TOTAL_PORTS; ++i) {
+ reportPINs[i] = false;
+ }
+ // TODO: load state from EEPROM here
+
+ /* send digital inputs here, if enabled, to set the initial state on the
+ * host computer, since once in the loop(), this firmware will only send
+ * digital data on change. */
+ if (reportPINs[0]) outputPort(0, PIND & ~ B00000011); // ignore Rx/Tx 0/1
+ if (reportPINs[1]) outputPort(1, PINB);
+ if (reportPINs[2]) outputPort(2, PINC);
+
+ Firmata.begin(115200);
+}
+
+/*==============================================================================
+ * LOOP()
+ *============================================================================*/
+void loop()
+{
+ /* DIGITALREAD - as fast as possible, check for changes and output them to the
+ * FTDI buffer using Serial.print() */
+ checkDigitalInputs();
+ currentMillis = millis();
+ if (currentMillis - previousMillis > 20) {
+ previousMillis += 20; // run this every 20ms
+ /* SERIALREAD - Serial.read() uses a 128 byte circular buffer, so handle
+ * all serialReads at once, i.e. empty the buffer */
+ while (Firmata.available())
+ Firmata.processInput();
+ /* SEND FTDI WRITE BUFFER - make sure that the FTDI buffer doesn't go over
+ * 60 bytes. use a timer to sending an event character every 4 ms to
+ * trigger the buffer to dump. */
+
+ /* ANALOGREAD - right after the event character, do all of the
+ * analogReads(). These only need to be done every 4ms. */
+ for (analogPin = 0; analogPin < TOTAL_ANALOG_PINS; analogPin++) {
+ if ( analogInputsToReport & (1 << analogPin) ) {
+ Firmata.sendAnalog(analogPin, analogRead(analogPin));
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Firmata is a generic protocol for communicating with microcontrollers
+ * from software on a host computer. It is intended to work with
+ * any host computer software package.
+ *
+ * To download a host software package, please click on the following link
+ * to open the download page in your default browser.
+ *
+ * http://firmata.org/wiki/Download
+ */
+
+/* This firmware supports as many servos as possible using the Servo library
+ * included in Arduino 0017
+ *
+ * This example code is in the public domain.
+ */
+
+#include <Servo.h>
+#include <Firmata.h>
+
+Servo servos[MAX_SERVOS];
+byte servoPinMap[TOTAL_PINS];
+byte servoCount = 0;
+
+void analogWriteCallback(byte pin, int value)
+{
+ if (IS_PIN_DIGITAL(pin)) {
+ servos[servoPinMap[pin]].write(value);
+ }
+}
+
+void systemResetCallback()
+{
+ servoCount = 0;
+}
+
+void setup()
+{
+ byte pin;
+
+ Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
+ Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
+ Firmata.attach(SYSTEM_RESET, systemResetCallback);
+
+ Firmata.begin(57600);
+ systemResetCallback();
+
+ // attach servos from first digital pin up to max number of
+ // servos supported for the board
+ for (pin = 0; pin < TOTAL_PINS; pin++) {
+ if (IS_PIN_DIGITAL(pin)) {
+ if (servoCount < MAX_SERVOS) {
+ servoPinMap[pin] = servoCount;
+ servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin));
+ servoCount++;
+ }
+ }
+ }
+}
+
+void loop()
+{
+ while (Firmata.available())
+ Firmata.processInput();
+}
--- /dev/null
+/*
+ * Firmata is a generic protocol for communicating with microcontrollers
+ * from software on a host computer. It is intended to work with
+ * any host computer software package.
+ *
+ * To download a host software package, please click on the following link
+ * to open the download page in your default browser.
+ *
+ * http://firmata.org/wiki/Download
+ */
+
+/* Supports as many analog inputs and analog PWM outputs as possible.
+ *
+ * This example code is in the public domain.
+ */
+#include <Firmata.h>
+
+byte analogPin = 0;
+
+void analogWriteCallback(byte pin, int value)
+{
+ if (IS_PIN_PWM(pin)) {
+ pinMode(PIN_TO_DIGITAL(pin), OUTPUT);
+ analogWrite(PIN_TO_PWM(pin), value);
+ }
+}
+
+void setup()
+{
+ Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
+ Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
+ Firmata.begin(57600);
+}
+
+void loop()
+{
+ while (Firmata.available()) {
+ Firmata.processInput();
+ }
+ // do one analogRead per loop, so if PC is sending a lot of
+ // analog write messages, we will only delay 1 analogRead
+ Firmata.sendAnalog(analogPin, analogRead(analogPin));
+ analogPin = analogPin + 1;
+ if (analogPin >= TOTAL_ANALOG_PINS) analogPin = 0;
+}
+
--- /dev/null
+/*
+ * Firmata is a generic protocol for communicating with microcontrollers
+ * from software on a host computer. It is intended to work with
+ * any host computer software package.
+ *
+ * To download a host software package, please click on the following link
+ * to open the download page in your default browser.
+ *
+ * http://firmata.org/wiki/Download
+ */
+
+/* Supports as many digital inputs and outputs as possible.
+ *
+ * This example code is in the public domain.
+ */
+#include <Firmata.h>
+
+byte previousPIN[TOTAL_PORTS]; // PIN means PORT for input
+byte previousPORT[TOTAL_PORTS];
+
+void outputPort(byte portNumber, byte portValue)
+{
+ // only send the data when it changes, otherwise you get too many messages!
+ if (previousPIN[portNumber] != portValue) {
+ Firmata.sendDigitalPort(portNumber, portValue);
+ previousPIN[portNumber] = portValue;
+ }
+}
+
+void setPinModeCallback(byte pin, int mode) {
+ if (IS_PIN_DIGITAL(pin)) {
+ pinMode(PIN_TO_DIGITAL(pin), mode);
+ }
+}
+
+void digitalWriteCallback(byte port, int value)
+{
+ byte i;
+ byte currentPinValue, previousPinValue;
+
+ if (port < TOTAL_PORTS && value != previousPORT[port]) {
+ for (i = 0; i < 8; i++) {
+ currentPinValue = (byte) value & (1 << i);
+ previousPinValue = previousPORT[port] & (1 << i);
+ if (currentPinValue != previousPinValue) {
+ digitalWrite(i + (port * 8), currentPinValue);
+ }
+ }
+ previousPORT[port] = value;
+ }
+}
+
+void setup()
+{
+ Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
+ Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
+ Firmata.attach(SET_PIN_MODE, setPinModeCallback);
+ Firmata.begin(57600);
+}
+
+void loop()
+{
+ byte i;
+
+ for (i = 0; i < TOTAL_PORTS; i++) {
+ outputPort(i, readPort(i, 0xff));
+ }
+
+ while (Firmata.available()) {
+ Firmata.processInput();
+ }
+}
--- /dev/null
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+\f
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
--- /dev/null
+/*
+ Firmata is a generic protocol for communicating with microcontrollers
+ from software on a host computer. It is intended to work with
+ any host computer software package.
+
+ To download a host software package, please click on the following link
+ to open the list of Firmata client libraries in your default browser.
+
+ https://github.com/firmata/arduino#firmata-client-libraries
+
+ Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.
+ Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved.
+ Copyright (C) 2009 Shigeru Kobayashi. All rights reserved.
+ Copyright (C) 2009-2016 Jeff Hoefs. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+
+ Last updated August 17th, 2017
+*/
+
+#include <Servo.h>
+#include <Wire.h>
+#include <Firmata.h>
+
+#define I2C_WRITE B00000000
+#define I2C_READ B00001000
+#define I2C_READ_CONTINUOUSLY B00010000
+#define I2C_STOP_READING B00011000
+#define I2C_READ_WRITE_MODE_MASK B00011000
+#define I2C_10BIT_ADDRESS_MODE_MASK B00100000
+#define I2C_END_TX_MASK B01000000
+#define I2C_STOP_TX 1
+#define I2C_RESTART_TX 0
+#define I2C_MAX_QUERIES 8
+#define I2C_REGISTER_NOT_SPECIFIED -1
+
+// the minimum interval for sampling analog input
+#define MINIMUM_SAMPLING_INTERVAL 1
+
+
+/*==============================================================================
+ * GLOBAL VARIABLES
+ *============================================================================*/
+
+#ifdef FIRMATA_SERIAL_FEATURE
+SerialFirmata serialFeature;
+#endif
+
+/* analog inputs */
+int analogInputsToReport = 0; // bitwise array to store pin reporting
+
+/* digital input ports */
+byte reportPINs[TOTAL_PORTS]; // 1 = report this port, 0 = silence
+byte previousPINs[TOTAL_PORTS]; // previous 8 bits sent
+
+/* pins configuration */
+byte portConfigInputs[TOTAL_PORTS]; // each bit: 1 = pin in INPUT, 0 = anything else
+
+/* timer variables */
+unsigned long currentMillis; // store the current value from millis()
+unsigned long previousMillis; // for comparison with currentMillis
+unsigned int samplingInterval = 19; // how often to run the main loop (in ms)
+
+/* i2c data */
+struct i2c_device_info {
+ byte addr;
+ int reg;
+ byte bytes;
+ byte stopTX;
+};
+
+/* for i2c read continuous more */
+i2c_device_info query[I2C_MAX_QUERIES];
+
+byte i2cRxData[64];
+boolean isI2CEnabled = false;
+signed char queryIndex = -1;
+// default delay time between i2c read request and Wire.requestFrom()
+unsigned int i2cReadDelayTime = 0;
+
+Servo servos[MAX_SERVOS];
+byte servoPinMap[TOTAL_PINS];
+byte detachedServos[MAX_SERVOS];
+byte detachedServoCount = 0;
+byte servoCount = 0;
+
+boolean isResetting = false;
+
+// Forward declare a few functions to avoid compiler errors with older versions
+// of the Arduino IDE.
+void setPinModeCallback(byte, int);
+void reportAnalogCallback(byte analogPin, int value);
+void sysexCallback(byte, byte, byte*);
+
+/* utility functions */
+void wireWrite(byte data)
+{
+#if ARDUINO >= 100
+ Wire.write((byte)data);
+#else
+ Wire.send(data);
+#endif
+}
+
+byte wireRead(void)
+{
+#if ARDUINO >= 100
+ return Wire.read();
+#else
+ return Wire.receive();
+#endif
+}
+
+/*==============================================================================
+ * FUNCTIONS
+ *============================================================================*/
+
+void attachServo(byte pin, int minPulse, int maxPulse)
+{
+ if (servoCount < MAX_SERVOS) {
+ // reuse indexes of detached servos until all have been reallocated
+ if (detachedServoCount > 0) {
+ servoPinMap[pin] = detachedServos[detachedServoCount - 1];
+ if (detachedServoCount > 0) detachedServoCount--;
+ } else {
+ servoPinMap[pin] = servoCount;
+ servoCount++;
+ }
+ if (minPulse > 0 && maxPulse > 0) {
+ servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin), minPulse, maxPulse);
+ } else {
+ servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin));
+ }
+ } else {
+ Firmata.sendString("Max servos attached");
+ }
+}
+
+void detachServo(byte pin)
+{
+ servos[servoPinMap[pin]].detach();
+ // if we're detaching the last servo, decrement the count
+ // otherwise store the index of the detached servo
+ if (servoPinMap[pin] == servoCount && servoCount > 0) {
+ servoCount--;
+ } else if (servoCount > 0) {
+ // keep track of detached servos because we want to reuse their indexes
+ // before incrementing the count of attached servos
+ detachedServoCount++;
+ detachedServos[detachedServoCount - 1] = servoPinMap[pin];
+ }
+
+ servoPinMap[pin] = 255;
+}
+
+void enableI2CPins()
+{
+ byte i;
+ // is there a faster way to do this? would probaby require importing
+ // Arduino.h to get SCL and SDA pins
+ for (i = 0; i < TOTAL_PINS; i++) {
+ if (IS_PIN_I2C(i)) {
+ // mark pins as i2c so they are ignore in non i2c data requests
+ setPinModeCallback(i, PIN_MODE_I2C);
+ }
+ }
+
+ isI2CEnabled = true;
+
+ Wire.begin();
+}
+
+/* disable the i2c pins so they can be used for other functions */
+void disableI2CPins() {
+ isI2CEnabled = false;
+ // disable read continuous mode for all devices
+ queryIndex = -1;
+}
+
+void readAndReportData(byte address, int theRegister, byte numBytes, byte stopTX) {
+ // allow I2C requests that don't require a register read
+ // for example, some devices using an interrupt pin to signify new data available
+ // do not always require the register read so upon interrupt you call Wire.requestFrom()
+ if (theRegister != I2C_REGISTER_NOT_SPECIFIED) {
+ Wire.beginTransmission(address);
+ wireWrite((byte)theRegister);
+ Wire.endTransmission(stopTX); // default = true
+ // do not set a value of 0
+ if (i2cReadDelayTime > 0) {
+ // delay is necessary for some devices such as WiiNunchuck
+ delayMicroseconds(i2cReadDelayTime);
+ }
+ } else {
+ theRegister = 0; // fill the register with a dummy value
+ }
+
+ Wire.requestFrom(address, numBytes); // all bytes are returned in requestFrom
+
+ // check to be sure correct number of bytes were returned by slave
+ if (numBytes < Wire.available()) {
+ Firmata.sendString("I2C: Too many bytes received");
+ } else if (numBytes > Wire.available()) {
+ Firmata.sendString("I2C: Too few bytes received");
+ }
+
+ i2cRxData[0] = address;
+ i2cRxData[1] = theRegister;
+
+ for (int i = 0; i < numBytes && Wire.available(); i++) {
+ i2cRxData[2 + i] = wireRead();
+ }
+
+ // send slave address, register and received bytes
+ Firmata.sendSysex(SYSEX_I2C_REPLY, numBytes + 2, i2cRxData);
+}
+
+void outputPort(byte portNumber, byte portValue, byte forceSend)
+{
+ // pins not configured as INPUT are cleared to zeros
+ portValue = portValue & portConfigInputs[portNumber];
+ // only send if the value is different than previously sent
+ if (forceSend || previousPINs[portNumber] != portValue) {
+ Firmata.sendDigitalPort(portNumber, portValue);
+ previousPINs[portNumber] = portValue;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * check all the active digital inputs for change of state, then add any events
+ * to the Serial output queue using Serial.print() */
+void checkDigitalInputs(void)
+{
+ /* Using non-looping code allows constants to be given to readPort().
+ * The compiler will apply substantial optimizations if the inputs
+ * to readPort() are compile-time constants. */
+ if (TOTAL_PORTS > 0 && reportPINs[0]) outputPort(0, readPort(0, portConfigInputs[0]), false);
+ if (TOTAL_PORTS > 1 && reportPINs[1]) outputPort(1, readPort(1, portConfigInputs[1]), false);
+ if (TOTAL_PORTS > 2 && reportPINs[2]) outputPort(2, readPort(2, portConfigInputs[2]), false);
+ if (TOTAL_PORTS > 3 && reportPINs[3]) outputPort(3, readPort(3, portConfigInputs[3]), false);
+ if (TOTAL_PORTS > 4 && reportPINs[4]) outputPort(4, readPort(4, portConfigInputs[4]), false);
+ if (TOTAL_PORTS > 5 && reportPINs[5]) outputPort(5, readPort(5, portConfigInputs[5]), false);
+ if (TOTAL_PORTS > 6 && reportPINs[6]) outputPort(6, readPort(6, portConfigInputs[6]), false);
+ if (TOTAL_PORTS > 7 && reportPINs[7]) outputPort(7, readPort(7, portConfigInputs[7]), false);
+ if (TOTAL_PORTS > 8 && reportPINs[8]) outputPort(8, readPort(8, portConfigInputs[8]), false);
+ if (TOTAL_PORTS > 9 && reportPINs[9]) outputPort(9, readPort(9, portConfigInputs[9]), false);
+ if (TOTAL_PORTS > 10 && reportPINs[10]) outputPort(10, readPort(10, portConfigInputs[10]), false);
+ if (TOTAL_PORTS > 11 && reportPINs[11]) outputPort(11, readPort(11, portConfigInputs[11]), false);
+ if (TOTAL_PORTS > 12 && reportPINs[12]) outputPort(12, readPort(12, portConfigInputs[12]), false);
+ if (TOTAL_PORTS > 13 && reportPINs[13]) outputPort(13, readPort(13, portConfigInputs[13]), false);
+ if (TOTAL_PORTS > 14 && reportPINs[14]) outputPort(14, readPort(14, portConfigInputs[14]), false);
+ if (TOTAL_PORTS > 15 && reportPINs[15]) outputPort(15, readPort(15, portConfigInputs[15]), false);
+}
+
+// -----------------------------------------------------------------------------
+/* sets the pin mode to the correct state and sets the relevant bits in the
+ * two bit-arrays that track Digital I/O and PWM status
+ */
+void setPinModeCallback(byte pin, int mode)
+{
+ if (Firmata.getPinMode(pin) == PIN_MODE_IGNORE)
+ return;
+
+ if (Firmata.getPinMode(pin) == PIN_MODE_I2C && isI2CEnabled && mode != PIN_MODE_I2C) {
+ // disable i2c so pins can be used for other functions
+ // the following if statements should reconfigure the pins properly
+ disableI2CPins();
+ }
+ if (IS_PIN_DIGITAL(pin) && mode != PIN_MODE_SERVO) {
+ if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) {
+ detachServo(pin);
+ }
+ }
+ if (IS_PIN_ANALOG(pin)) {
+ reportAnalogCallback(PIN_TO_ANALOG(pin), mode == PIN_MODE_ANALOG ? 1 : 0); // turn on/off reporting
+ }
+ if (IS_PIN_DIGITAL(pin)) {
+ if (mode == INPUT || mode == PIN_MODE_PULLUP) {
+ portConfigInputs[pin / 8] |= (1 << (pin & 7));
+ } else {
+ portConfigInputs[pin / 8] &= ~(1 << (pin & 7));
+ }
+ }
+ Firmata.setPinState(pin, 0);
+ switch (mode) {
+ case PIN_MODE_ANALOG:
+ if (IS_PIN_ANALOG(pin)) {
+ if (IS_PIN_DIGITAL(pin)) {
+ pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
+#if ARDUINO <= 100
+ // deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6
+ digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
+#endif
+ }
+ Firmata.setPinMode(pin, PIN_MODE_ANALOG);
+ }
+ break;
+ case INPUT:
+ if (IS_PIN_DIGITAL(pin)) {
+ pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
+#if ARDUINO <= 100
+ // deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6
+ digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
+#endif
+ Firmata.setPinMode(pin, INPUT);
+ }
+ break;
+ case PIN_MODE_PULLUP:
+ if (IS_PIN_DIGITAL(pin)) {
+ pinMode(PIN_TO_DIGITAL(pin), INPUT_PULLUP);
+ Firmata.setPinMode(pin, PIN_MODE_PULLUP);
+ Firmata.setPinState(pin, 1);
+ }
+ break;
+ case OUTPUT:
+ if (IS_PIN_DIGITAL(pin)) {
+ if (Firmata.getPinMode(pin) == PIN_MODE_PWM) {
+ // Disable PWM if pin mode was previously set to PWM.
+ digitalWrite(PIN_TO_DIGITAL(pin), LOW);
+ }
+ pinMode(PIN_TO_DIGITAL(pin), OUTPUT);
+ Firmata.setPinMode(pin, OUTPUT);
+ }
+ break;
+ case PIN_MODE_PWM:
+ if (IS_PIN_PWM(pin)) {
+ pinMode(PIN_TO_PWM(pin), OUTPUT);
+ analogWrite(PIN_TO_PWM(pin), 0);
+ Firmata.setPinMode(pin, PIN_MODE_PWM);
+ }
+ break;
+ case PIN_MODE_SERVO:
+ if (IS_PIN_DIGITAL(pin)) {
+ Firmata.setPinMode(pin, PIN_MODE_SERVO);
+ if (servoPinMap[pin] == 255 || !servos[servoPinMap[pin]].attached()) {
+ // pass -1 for min and max pulse values to use default values set
+ // by Servo library
+ attachServo(pin, -1, -1);
+ }
+ }
+ break;
+ case PIN_MODE_I2C:
+ if (IS_PIN_I2C(pin)) {
+ // mark the pin as i2c
+ // the user must call I2C_CONFIG to enable I2C for a device
+ Firmata.setPinMode(pin, PIN_MODE_I2C);
+ }
+ break;
+ case PIN_MODE_SERIAL:
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.handlePinMode(pin, PIN_MODE_SERIAL);
+#endif
+ break;
+ default:
+ Firmata.sendString("Unknown pin mode"); // TODO: put error msgs in EEPROM
+ }
+ // TODO: save status to EEPROM here, if changed
+}
+
+/*
+ * Sets the value of an individual pin. Useful if you want to set a pin value but
+ * are not tracking the digital port state.
+ * Can only be used on pins configured as OUTPUT.
+ * Cannot be used to enable pull-ups on Digital INPUT pins.
+ */
+void setPinValueCallback(byte pin, int value)
+{
+ if (pin < TOTAL_PINS && IS_PIN_DIGITAL(pin)) {
+ if (Firmata.getPinMode(pin) == OUTPUT) {
+ Firmata.setPinState(pin, value);
+ digitalWrite(PIN_TO_DIGITAL(pin), value);
+ }
+ }
+}
+
+void analogWriteCallback(byte pin, int value)
+{
+ if (pin < TOTAL_PINS) {
+ switch (Firmata.getPinMode(pin)) {
+ case PIN_MODE_SERVO:
+ if (IS_PIN_DIGITAL(pin))
+ servos[servoPinMap[pin]].write(value);
+ Firmata.setPinState(pin, value);
+ break;
+ case PIN_MODE_PWM:
+ if (IS_PIN_PWM(pin))
+ analogWrite(PIN_TO_PWM(pin), value);
+ Firmata.setPinState(pin, value);
+ break;
+ }
+ }
+}
+
+void digitalWriteCallback(byte port, int value)
+{
+ byte pin, lastPin, pinValue, mask = 1, pinWriteMask = 0;
+
+ if (port < TOTAL_PORTS) {
+ // create a mask of the pins on this port that are writable.
+ lastPin = port * 8 + 8;
+ if (lastPin > TOTAL_PINS) lastPin = TOTAL_PINS;
+ for (pin = port * 8; pin < lastPin; pin++) {
+ // do not disturb non-digital pins (eg, Rx & Tx)
+ if (IS_PIN_DIGITAL(pin)) {
+ // do not touch pins in PWM, ANALOG, SERVO or other modes
+ if (Firmata.getPinMode(pin) == OUTPUT || Firmata.getPinMode(pin) == INPUT) {
+ pinValue = ((byte)value & mask) ? 1 : 0;
+ if (Firmata.getPinMode(pin) == OUTPUT) {
+ pinWriteMask |= mask;
+ } else if (Firmata.getPinMode(pin) == INPUT && pinValue == 1 && Firmata.getPinState(pin) != 1) {
+ // only handle INPUT here for backwards compatibility
+#if ARDUINO > 100
+ pinMode(pin, INPUT_PULLUP);
+#else
+ // only write to the INPUT pin to enable pullups if Arduino v1.0.0 or earlier
+ pinWriteMask |= mask;
+#endif
+ }
+ Firmata.setPinState(pin, pinValue);
+ }
+ }
+ mask = mask << 1;
+ }
+ writePort(port, (byte)value, pinWriteMask);
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+/* sets bits in a bit array (int) to toggle the reporting of the analogIns
+ */
+//void FirmataClass::setAnalogPinReporting(byte pin, byte state) {
+//}
+void reportAnalogCallback(byte analogPin, int value)
+{
+ if (analogPin < TOTAL_ANALOG_PINS) {
+ if (value == 0) {
+ analogInputsToReport = analogInputsToReport & ~ (1 << analogPin);
+ } else {
+ analogInputsToReport = analogInputsToReport | (1 << analogPin);
+ // prevent during system reset or all analog pin values will be reported
+ // which may report noise for unconnected analog pins
+ if (!isResetting) {
+ // Send pin value immediately. This is helpful when connected via
+ // ethernet, wi-fi or bluetooth so pin states can be known upon
+ // reconnecting.
+ Firmata.sendAnalog(analogPin, analogRead(analogPin));
+ }
+ }
+ }
+ // TODO: save status to EEPROM here, if changed
+}
+
+void reportDigitalCallback(byte port, int value)
+{
+ if (port < TOTAL_PORTS) {
+ reportPINs[port] = (byte)value;
+ // Send port value immediately. This is helpful when connected via
+ // ethernet, wi-fi or bluetooth so pin states can be known upon
+ // reconnecting.
+ if (value) outputPort(port, readPort(port, portConfigInputs[port]), true);
+ }
+ // do not disable analog reporting on these 8 pins, to allow some
+ // pins used for digital, others analog. Instead, allow both types
+ // of reporting to be enabled, but check if the pin is configured
+ // as analog when sampling the analog inputs. Likewise, while
+ // scanning digital pins, portConfigInputs will mask off values from any
+ // pins configured as analog
+}
+
+/*==============================================================================
+ * SYSEX-BASED commands
+ *============================================================================*/
+
+void sysexCallback(byte command, byte argc, byte *argv)
+{
+ byte mode;
+ byte stopTX;
+ byte slaveAddress;
+ byte data;
+ int slaveRegister;
+ unsigned int delayTime;
+
+ switch (command) {
+ case I2C_REQUEST:
+ mode = argv[1] & I2C_READ_WRITE_MODE_MASK;
+ if (argv[1] & I2C_10BIT_ADDRESS_MODE_MASK) {
+ Firmata.sendString("10-bit addressing not supported");
+ return;
+ }
+ else {
+ slaveAddress = argv[0];
+ }
+
+ // need to invert the logic here since 0 will be default for client
+ // libraries that have not updated to add support for restart tx
+ if (argv[1] & I2C_END_TX_MASK) {
+ stopTX = I2C_RESTART_TX;
+ }
+ else {
+ stopTX = I2C_STOP_TX; // default
+ }
+
+ switch (mode) {
+ case I2C_WRITE:
+ Wire.beginTransmission(slaveAddress);
+ for (byte i = 2; i < argc; i += 2) {
+ data = argv[i] + (argv[i + 1] << 7);
+ wireWrite(data);
+ }
+ Wire.endTransmission();
+ delayMicroseconds(70);
+ break;
+ case I2C_READ:
+ if (argc == 6) {
+ // a slave register is specified
+ slaveRegister = argv[2] + (argv[3] << 7);
+ data = argv[4] + (argv[5] << 7); // bytes to read
+ }
+ else {
+ // a slave register is NOT specified
+ slaveRegister = I2C_REGISTER_NOT_SPECIFIED;
+ data = argv[2] + (argv[3] << 7); // bytes to read
+ }
+ readAndReportData(slaveAddress, (int)slaveRegister, data, stopTX);
+ break;
+ case I2C_READ_CONTINUOUSLY:
+ if ((queryIndex + 1) >= I2C_MAX_QUERIES) {
+ // too many queries, just ignore
+ Firmata.sendString("too many queries");
+ break;
+ }
+ if (argc == 6) {
+ // a slave register is specified
+ slaveRegister = argv[2] + (argv[3] << 7);
+ data = argv[4] + (argv[5] << 7); // bytes to read
+ }
+ else {
+ // a slave register is NOT specified
+ slaveRegister = (int)I2C_REGISTER_NOT_SPECIFIED;
+ data = argv[2] + (argv[3] << 7); // bytes to read
+ }
+ queryIndex++;
+ query[queryIndex].addr = slaveAddress;
+ query[queryIndex].reg = slaveRegister;
+ query[queryIndex].bytes = data;
+ query[queryIndex].stopTX = stopTX;
+ break;
+ case I2C_STOP_READING:
+ byte queryIndexToSkip;
+ // if read continuous mode is enabled for only 1 i2c device, disable
+ // read continuous reporting for that device
+ if (queryIndex <= 0) {
+ queryIndex = -1;
+ } else {
+ queryIndexToSkip = 0;
+ // if read continuous mode is enabled for multiple devices,
+ // determine which device to stop reading and remove it's data from
+ // the array, shifiting other array data to fill the space
+ for (byte i = 0; i < queryIndex + 1; i++) {
+ if (query[i].addr == slaveAddress) {
+ queryIndexToSkip = i;
+ break;
+ }
+ }
+
+ for (byte i = queryIndexToSkip; i < queryIndex + 1; i++) {
+ if (i < I2C_MAX_QUERIES) {
+ query[i].addr = query[i + 1].addr;
+ query[i].reg = query[i + 1].reg;
+ query[i].bytes = query[i + 1].bytes;
+ query[i].stopTX = query[i + 1].stopTX;
+ }
+ }
+ queryIndex--;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case I2C_CONFIG:
+ delayTime = (argv[0] + (argv[1] << 7));
+
+ if (argc > 1 && delayTime > 0) {
+ i2cReadDelayTime = delayTime;
+ }
+
+ if (!isI2CEnabled) {
+ enableI2CPins();
+ }
+
+ break;
+ case SERVO_CONFIG:
+ if (argc > 4) {
+ // these vars are here for clarity, they'll optimized away by the compiler
+ byte pin = argv[0];
+ int minPulse = argv[1] + (argv[2] << 7);
+ int maxPulse = argv[3] + (argv[4] << 7);
+
+ if (IS_PIN_DIGITAL(pin)) {
+ if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) {
+ detachServo(pin);
+ }
+ attachServo(pin, minPulse, maxPulse);
+ setPinModeCallback(pin, PIN_MODE_SERVO);
+ }
+ }
+ break;
+ case SAMPLING_INTERVAL:
+ if (argc > 1) {
+ samplingInterval = argv[0] + (argv[1] << 7);
+ if (samplingInterval < MINIMUM_SAMPLING_INTERVAL) {
+ samplingInterval = MINIMUM_SAMPLING_INTERVAL;
+ }
+ } else {
+ //Firmata.sendString("Not enough data");
+ }
+ break;
+ case EXTENDED_ANALOG:
+ if (argc > 1) {
+ int val = argv[1];
+ if (argc > 2) val |= (argv[2] << 7);
+ if (argc > 3) val |= (argv[3] << 14);
+ analogWriteCallback(argv[0], val);
+ }
+ break;
+ case CAPABILITY_QUERY:
+ Firmata.write(START_SYSEX);
+ Firmata.write(CAPABILITY_RESPONSE);
+ for (byte pin = 0; pin < TOTAL_PINS; pin++) {
+ if (IS_PIN_DIGITAL(pin)) {
+ Firmata.write((byte)INPUT);
+ Firmata.write(1);
+ Firmata.write((byte)PIN_MODE_PULLUP);
+ Firmata.write(1);
+ Firmata.write((byte)OUTPUT);
+ Firmata.write(1);
+ }
+ if (IS_PIN_ANALOG(pin)) {
+ Firmata.write(PIN_MODE_ANALOG);
+ Firmata.write(10); // 10 = 10-bit resolution
+ }
+ if (IS_PIN_PWM(pin)) {
+ Firmata.write(PIN_MODE_PWM);
+ Firmata.write(DEFAULT_PWM_RESOLUTION);
+ }
+ if (IS_PIN_DIGITAL(pin)) {
+ Firmata.write(PIN_MODE_SERVO);
+ Firmata.write(14);
+ }
+ if (IS_PIN_I2C(pin)) {
+ Firmata.write(PIN_MODE_I2C);
+ Firmata.write(1); // TODO: could assign a number to map to SCL or SDA
+ }
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.handleCapability(pin);
+#endif
+ Firmata.write(127);
+ }
+ Firmata.write(END_SYSEX);
+ break;
+ case PIN_STATE_QUERY:
+ if (argc > 0) {
+ byte pin = argv[0];
+ Firmata.write(START_SYSEX);
+ Firmata.write(PIN_STATE_RESPONSE);
+ Firmata.write(pin);
+ if (pin < TOTAL_PINS) {
+ Firmata.write(Firmata.getPinMode(pin));
+ Firmata.write((byte)Firmata.getPinState(pin) & 0x7F);
+ if (Firmata.getPinState(pin) & 0xFF80) Firmata.write((byte)(Firmata.getPinState(pin) >> 7) & 0x7F);
+ if (Firmata.getPinState(pin) & 0xC000) Firmata.write((byte)(Firmata.getPinState(pin) >> 14) & 0x7F);
+ }
+ Firmata.write(END_SYSEX);
+ }
+ break;
+ case ANALOG_MAPPING_QUERY:
+ Firmata.write(START_SYSEX);
+ Firmata.write(ANALOG_MAPPING_RESPONSE);
+ for (byte pin = 0; pin < TOTAL_PINS; pin++) {
+ Firmata.write(IS_PIN_ANALOG(pin) ? PIN_TO_ANALOG(pin) : 127);
+ }
+ Firmata.write(END_SYSEX);
+ break;
+
+ case SERIAL_MESSAGE:
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.handleSysex(command, argc, argv);
+#endif
+ break;
+ }
+}
+
+/*==============================================================================
+ * SETUP()
+ *============================================================================*/
+
+void systemResetCallback()
+{
+ isResetting = true;
+
+ // initialize a defalt state
+ // TODO: option to load config from EEPROM instead of default
+
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.reset();
+#endif
+
+ if (isI2CEnabled) {
+ disableI2CPins();
+ }
+
+ for (byte i = 0; i < TOTAL_PORTS; i++) {
+ reportPINs[i] = false; // by default, reporting off
+ portConfigInputs[i] = 0; // until activated
+ previousPINs[i] = 0;
+ }
+
+ for (byte i = 0; i < TOTAL_PINS; i++) {
+ // pins with analog capability default to analog input
+ // otherwise, pins default to digital output
+ if (IS_PIN_ANALOG(i)) {
+ // turns off pullup, configures everything
+ setPinModeCallback(i, PIN_MODE_ANALOG);
+ } else if (IS_PIN_DIGITAL(i)) {
+ // sets the output to 0, configures portConfigInputs
+ setPinModeCallback(i, OUTPUT);
+ }
+
+ servoPinMap[i] = 255;
+ }
+ // by default, do not report any analog inputs
+ analogInputsToReport = 0;
+
+ detachedServoCount = 0;
+ servoCount = 0;
+
+ /* send digital inputs to set the initial state on the host computer,
+ * since once in the loop(), this firmware will only send on change */
+ /*
+ TODO: this can never execute, since no pins default to digital input
+ but it will be needed when/if we support EEPROM stored config
+ for (byte i=0; i < TOTAL_PORTS; i++) {
+ outputPort(i, readPort(i, portConfigInputs[i]), true);
+ }
+ */
+ isResetting = false;
+}
+
+void setup()
+{
+ Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
+
+ Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
+ Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
+ Firmata.attach(REPORT_ANALOG, reportAnalogCallback);
+ Firmata.attach(REPORT_DIGITAL, reportDigitalCallback);
+ Firmata.attach(SET_PIN_MODE, setPinModeCallback);
+ Firmata.attach(SET_DIGITAL_PIN_VALUE, setPinValueCallback);
+ Firmata.attach(START_SYSEX, sysexCallback);
+ Firmata.attach(SYSTEM_RESET, systemResetCallback);
+
+ // to use a port other than Serial, such as Serial1 on an Arduino Leonardo or Mega,
+ // Call begin(baud) on the alternate serial port and pass it to Firmata to begin like this:
+ // Serial1.begin(57600);
+ // Firmata.begin(Serial1);
+ // However do not do this if you are using SERIAL_MESSAGE
+
+ Firmata.begin(57600);
+ while (!Serial) {
+ ; // wait for serial port to connect. Needed for ATmega32u4-based boards and Arduino 101
+ }
+
+ systemResetCallback(); // reset to default config
+}
+
+/*==============================================================================
+ * LOOP()
+ *============================================================================*/
+void loop()
+{
+ byte pin, analogPin;
+
+ /* DIGITALREAD - as fast as possible, check for changes and output them to the
+ * FTDI buffer using Serial.print() */
+ checkDigitalInputs();
+
+ /* STREAMREAD - processing incoming messagse as soon as possible, while still
+ * checking digital inputs. */
+ while (Firmata.available())
+ Firmata.processInput();
+
+ // TODO - ensure that Stream buffer doesn't go over 60 bytes
+
+ currentMillis = millis();
+ if (currentMillis - previousMillis > samplingInterval) {
+ previousMillis += samplingInterval;
+ /* ANALOGREAD - do all analogReads() at the configured sampling interval */
+ for (pin = 0; pin < TOTAL_PINS; pin++) {
+ if (IS_PIN_ANALOG(pin) && Firmata.getPinMode(pin) == PIN_MODE_ANALOG) {
+ analogPin = PIN_TO_ANALOG(pin);
+ if (analogInputsToReport & (1 << analogPin)) {
+ Firmata.sendAnalog(analogPin, analogRead(analogPin));
+ }
+ }
+ }
+ // report i2c data for all device with read continuous mode enabled
+ if (queryIndex > -1) {
+ for (byte i = 0; i < queryIndex + 1; i++) {
+ readAndReportData(query[i].addr, query[i].reg, query[i].bytes, query[i].stopTX);
+ }
+ }
+ }
+
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.update();
+#endif
+}
--- /dev/null
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+\f
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
--- /dev/null
+/*
+ Firmata is a generic protocol for communicating with microcontrollers
+ from software on a host computer. It is intended to work with
+ any host computer software package.
+
+ To download a host software package, please click on the following link
+ to open the list of Firmata client libraries in your default browser.
+
+ https://github.com/firmata/arduino#firmata-client-libraries
+
+ Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.
+ Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved.
+ Copyright (C) 2009 Shigeru Kobayashi. All rights reserved.
+ Copyright (C) 2009-2016 Jeff Hoefs. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+
+ Last updated August 17th, 2017
+*/
+
+#include <Servo.h>
+#include <Wire.h>
+#include <Firmata.h>
+
+//#define SERIAL_DEBUG
+#include "utility/firmataDebug.h"
+
+/*
+ * Uncomment the following include to enable interfacing
+ * with Serial devices via hardware or software serial.
+ */
+// In order to use software serial, you will need to compile this sketch with
+// Arduino IDE v1.6.6 or higher. Hardware serial should work back to Arduino 1.0.
+//#include "utility/SerialFirmata.h"
+
+// follow the instructions in bleConfig.h to configure your BLE hardware
+#include "bleConfig.h"
+
+#define I2C_WRITE 0x00 //B00000000
+#define I2C_READ 0x08 //B00001000
+#define I2C_READ_CONTINUOUSLY 0x10 //B00010000
+#define I2C_STOP_READING 0x18 //B00011000
+#define I2C_READ_WRITE_MODE_MASK 0x18 //B00011000
+#define I2C_10BIT_ADDRESS_MODE_MASK 0x20 //B00100000
+#define I2C_END_TX_MASK 0x40 //B01000000
+#define I2C_STOP_TX 1
+#define I2C_RESTART_TX 0
+#define I2C_MAX_QUERIES 8
+#define I2C_REGISTER_NOT_SPECIFIED -1
+
+// the minimum interval for sampling analog input
+#define MINIMUM_SAMPLING_INTERVAL 1
+
+// min cannot be < 0x0006. Adjust max if necessary
+#define FIRMATA_BLE_MIN_INTERVAL 0x0006 // 7.5ms (7.5 / 1.25)
+#define FIRMATA_BLE_MAX_INTERVAL 0x0018 // 30ms (30 / 1.25)
+
+/*==============================================================================
+ * GLOBAL VARIABLES
+ *============================================================================*/
+
+#ifdef FIRMATA_SERIAL_FEATURE
+SerialFirmata serialFeature;
+#endif
+
+/* analog inputs */
+int analogInputsToReport = 0; // bitwise array to store pin reporting
+
+/* digital input ports */
+byte reportPINs[TOTAL_PORTS]; // 1 = report this port, 0 = silence
+byte previousPINs[TOTAL_PORTS]; // previous 8 bits sent
+
+/* pins configuration */
+byte portConfigInputs[TOTAL_PORTS]; // each bit: 1 = pin in INPUT, 0 = anything else
+
+/* timer variables */
+unsigned long currentMillis; // store the current value from millis()
+unsigned long previousMillis; // for comparison with currentMillis
+unsigned int samplingInterval = 19; // how often to run the main loop (in ms)
+
+/* i2c data */
+struct i2c_device_info {
+ byte addr;
+ int reg;
+ byte bytes;
+ byte stopTX;
+};
+
+/* for i2c read continuous more */
+i2c_device_info query[I2C_MAX_QUERIES];
+
+byte i2cRxData[64];
+boolean isI2CEnabled = false;
+signed char queryIndex = -1;
+// default delay time between i2c read request and Wire.requestFrom()
+unsigned int i2cReadDelayTime = 0;
+
+Servo servos[MAX_SERVOS];
+byte servoPinMap[TOTAL_PINS];
+byte detachedServos[MAX_SERVOS];
+byte detachedServoCount = 0;
+byte servoCount = 0;
+
+boolean isResetting = false;
+
+// Forward declare a few functions to avoid compiler errors with older versions
+// of the Arduino IDE.
+void setPinModeCallback(byte, int);
+void reportAnalogCallback(byte analogPin, int value);
+void sysexCallback(byte, byte, byte*);
+
+/* utility functions */
+void wireWrite(byte data)
+{
+#if ARDUINO >= 100
+ Wire.write((byte)data);
+#else
+ Wire.send(data);
+#endif
+}
+
+byte wireRead(void)
+{
+#if ARDUINO >= 100
+ return Wire.read();
+#else
+ return Wire.receive();
+#endif
+}
+
+/*==============================================================================
+ * FUNCTIONS
+ *============================================================================*/
+
+void attachServo(byte pin, int minPulse, int maxPulse)
+{
+ if (servoCount < MAX_SERVOS) {
+ // reuse indexes of detached servos until all have been reallocated
+ if (detachedServoCount > 0) {
+ servoPinMap[pin] = detachedServos[detachedServoCount - 1];
+ if (detachedServoCount > 0) detachedServoCount--;
+ } else {
+ servoPinMap[pin] = servoCount;
+ servoCount++;
+ }
+ if (minPulse > 0 && maxPulse > 0) {
+ servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin), minPulse, maxPulse);
+ } else {
+ servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin));
+ }
+ } else {
+ Firmata.sendString("Max servos attached");
+ }
+}
+
+void detachServo(byte pin)
+{
+ servos[servoPinMap[pin]].detach();
+ // if we're detaching the last servo, decrement the count
+ // otherwise store the index of the detached servo
+ if (servoPinMap[pin] == servoCount && servoCount > 0) {
+ servoCount--;
+ } else if (servoCount > 0) {
+ // keep track of detached servos because we want to reuse their indexes
+ // before incrementing the count of attached servos
+ detachedServoCount++;
+ detachedServos[detachedServoCount - 1] = servoPinMap[pin];
+ }
+
+ servoPinMap[pin] = 255;
+}
+
+void enableI2CPins()
+{
+ byte i;
+ // is there a faster way to do this? would probaby require importing
+ // Arduino.h to get SCL and SDA pins
+ for (i = 0; i < TOTAL_PINS; i++) {
+ if (IS_PIN_I2C(i)) {
+ // mark pins as i2c so they are ignore in non i2c data requests
+ setPinModeCallback(i, PIN_MODE_I2C);
+ }
+ }
+
+ isI2CEnabled = true;
+
+ Wire.begin();
+}
+
+/* disable the i2c pins so they can be used for other functions */
+void disableI2CPins() {
+ isI2CEnabled = false;
+ // disable read continuous mode for all devices
+ queryIndex = -1;
+}
+
+void readAndReportData(byte address, int theRegister, byte numBytes, byte stopTX) {
+ // allow I2C requests that don't require a register read
+ // for example, some devices using an interrupt pin to signify new data available
+ // do not always require the register read so upon interrupt you call Wire.requestFrom()
+ if (theRegister != I2C_REGISTER_NOT_SPECIFIED) {
+ Wire.beginTransmission(address);
+ wireWrite((byte)theRegister);
+ Wire.endTransmission(stopTX); // default = true
+ // do not set a value of 0
+ if (i2cReadDelayTime > 0) {
+ // delay is necessary for some devices such as WiiNunchuck
+ delayMicroseconds(i2cReadDelayTime);
+ }
+ } else {
+ theRegister = 0; // fill the register with a dummy value
+ }
+
+ Wire.requestFrom(address, numBytes); // all bytes are returned in requestFrom
+
+ // check to be sure correct number of bytes were returned by slave
+ if (numBytes < Wire.available()) {
+ Firmata.sendString("I2C: Too many bytes received");
+ } else if (numBytes > Wire.available()) {
+ Firmata.sendString("I2C: Too few bytes received");
+ }
+
+ i2cRxData[0] = address;
+ i2cRxData[1] = theRegister;
+
+ for (int i = 0; i < numBytes && Wire.available(); i++) {
+ i2cRxData[2 + i] = wireRead();
+ }
+
+ // send slave address, register and received bytes
+ Firmata.sendSysex(SYSEX_I2C_REPLY, numBytes + 2, i2cRxData);
+}
+
+void outputPort(byte portNumber, byte portValue, byte forceSend)
+{
+ // pins not configured as INPUT are cleared to zeros
+ portValue = portValue & portConfigInputs[portNumber];
+ // only send if the value is different than previously sent
+ if (forceSend || previousPINs[portNumber] != portValue) {
+ Firmata.sendDigitalPort(portNumber, portValue);
+ previousPINs[portNumber] = portValue;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * check all the active digital inputs for change of state, then add any events
+ * to the Serial output queue using Serial.print() */
+void checkDigitalInputs(void)
+{
+ /* Using non-looping code allows constants to be given to readPort().
+ * The compiler will apply substantial optimizations if the inputs
+ * to readPort() are compile-time constants. */
+ if (TOTAL_PORTS > 0 && reportPINs[0]) outputPort(0, readPort(0, portConfigInputs[0]), false);
+ if (TOTAL_PORTS > 1 && reportPINs[1]) outputPort(1, readPort(1, portConfigInputs[1]), false);
+ if (TOTAL_PORTS > 2 && reportPINs[2]) outputPort(2, readPort(2, portConfigInputs[2]), false);
+ if (TOTAL_PORTS > 3 && reportPINs[3]) outputPort(3, readPort(3, portConfigInputs[3]), false);
+ if (TOTAL_PORTS > 4 && reportPINs[4]) outputPort(4, readPort(4, portConfigInputs[4]), false);
+ if (TOTAL_PORTS > 5 && reportPINs[5]) outputPort(5, readPort(5, portConfigInputs[5]), false);
+ if (TOTAL_PORTS > 6 && reportPINs[6]) outputPort(6, readPort(6, portConfigInputs[6]), false);
+ if (TOTAL_PORTS > 7 && reportPINs[7]) outputPort(7, readPort(7, portConfigInputs[7]), false);
+ if (TOTAL_PORTS > 8 && reportPINs[8]) outputPort(8, readPort(8, portConfigInputs[8]), false);
+ if (TOTAL_PORTS > 9 && reportPINs[9]) outputPort(9, readPort(9, portConfigInputs[9]), false);
+ if (TOTAL_PORTS > 10 && reportPINs[10]) outputPort(10, readPort(10, portConfigInputs[10]), false);
+ if (TOTAL_PORTS > 11 && reportPINs[11]) outputPort(11, readPort(11, portConfigInputs[11]), false);
+ if (TOTAL_PORTS > 12 && reportPINs[12]) outputPort(12, readPort(12, portConfigInputs[12]), false);
+ if (TOTAL_PORTS > 13 && reportPINs[13]) outputPort(13, readPort(13, portConfigInputs[13]), false);
+ if (TOTAL_PORTS > 14 && reportPINs[14]) outputPort(14, readPort(14, portConfigInputs[14]), false);
+ if (TOTAL_PORTS > 15 && reportPINs[15]) outputPort(15, readPort(15, portConfigInputs[15]), false);
+}
+
+// -----------------------------------------------------------------------------
+/* sets the pin mode to the correct state and sets the relevant bits in the
+ * two bit-arrays that track Digital I/O and PWM status
+ */
+void setPinModeCallback(byte pin, int mode)
+{
+ if (Firmata.getPinMode(pin) == PIN_MODE_IGNORE)
+ return;
+
+ if (Firmata.getPinMode(pin) == PIN_MODE_I2C && isI2CEnabled && mode != PIN_MODE_I2C) {
+ // disable i2c so pins can be used for other functions
+ // the following if statements should reconfigure the pins properly
+ disableI2CPins();
+ }
+ if (IS_PIN_DIGITAL(pin) && mode != PIN_MODE_SERVO) {
+ if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) {
+ detachServo(pin);
+ }
+ }
+ if (IS_PIN_ANALOG(pin)) {
+ reportAnalogCallback(PIN_TO_ANALOG(pin), mode == PIN_MODE_ANALOG ? 1 : 0); // turn on/off reporting
+ }
+ if (IS_PIN_DIGITAL(pin)) {
+ if (mode == INPUT || mode == PIN_MODE_PULLUP) {
+ portConfigInputs[pin / 8] |= (1 << (pin & 7));
+ } else {
+ portConfigInputs[pin / 8] &= ~(1 << (pin & 7));
+ }
+ }
+ Firmata.setPinState(pin, 0);
+ switch (mode) {
+ case PIN_MODE_ANALOG:
+ if (IS_PIN_ANALOG(pin)) {
+ if (IS_PIN_DIGITAL(pin)) {
+ pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
+#if ARDUINO <= 100
+ // deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6
+ digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
+#endif
+ }
+ Firmata.setPinMode(pin, PIN_MODE_ANALOG);
+ }
+ break;
+ case INPUT:
+ if (IS_PIN_DIGITAL(pin)) {
+ pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
+#if ARDUINO <= 100
+ // deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6
+ digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
+#endif
+ Firmata.setPinMode(pin, INPUT);
+ }
+ break;
+ case PIN_MODE_PULLUP:
+ if (IS_PIN_DIGITAL(pin)) {
+ pinMode(PIN_TO_DIGITAL(pin), INPUT_PULLUP);
+ Firmata.setPinMode(pin, PIN_MODE_PULLUP);
+ Firmata.setPinState(pin, 1);
+ }
+ break;
+ case OUTPUT:
+ if (IS_PIN_DIGITAL(pin)) {
+ if (Firmata.getPinMode(pin) == PIN_MODE_PWM) {
+ // Disable PWM if pin mode was previously set to PWM.
+ digitalWrite(PIN_TO_DIGITAL(pin), LOW);
+ }
+ pinMode(PIN_TO_DIGITAL(pin), OUTPUT);
+ Firmata.setPinMode(pin, OUTPUT);
+ }
+ break;
+ case PIN_MODE_PWM:
+ if (IS_PIN_PWM(pin)) {
+ pinMode(PIN_TO_PWM(pin), OUTPUT);
+ analogWrite(PIN_TO_PWM(pin), 0);
+ Firmata.setPinMode(pin, PIN_MODE_PWM);
+ }
+ break;
+ case PIN_MODE_SERVO:
+ if (IS_PIN_DIGITAL(pin)) {
+ Firmata.setPinMode(pin, PIN_MODE_SERVO);
+ if (servoPinMap[pin] == 255 || !servos[servoPinMap[pin]].attached()) {
+ // pass -1 for min and max pulse values to use default values set
+ // by Servo library
+ attachServo(pin, -1, -1);
+ }
+ }
+ break;
+ case PIN_MODE_I2C:
+ if (IS_PIN_I2C(pin)) {
+ // mark the pin as i2c
+ // the user must call I2C_CONFIG to enable I2C for a device
+ Firmata.setPinMode(pin, PIN_MODE_I2C);
+ }
+ break;
+ case PIN_MODE_SERIAL:
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.handlePinMode(pin, PIN_MODE_SERIAL);
+#endif
+ break;
+ default:
+ Firmata.sendString("Unknown pin mode"); // TODO: put error msgs in EEPROM
+ }
+ // TODO: save status to EEPROM here, if changed
+}
+
+/*
+ * Sets the value of an individual pin. Useful if you want to set a pin value but
+ * are not tracking the digital port state.
+ * Can only be used on pins configured as OUTPUT.
+ * Cannot be used to enable pull-ups on Digital INPUT pins.
+ */
+void setPinValueCallback(byte pin, int value)
+{
+ if (pin < TOTAL_PINS && IS_PIN_DIGITAL(pin)) {
+ if (Firmata.getPinMode(pin) == OUTPUT) {
+ Firmata.setPinState(pin, value);
+ digitalWrite(PIN_TO_DIGITAL(pin), value);
+ }
+ }
+}
+
+void analogWriteCallback(byte pin, int value)
+{
+ if (pin < TOTAL_PINS) {
+ switch (Firmata.getPinMode(pin)) {
+ case PIN_MODE_SERVO:
+ if (IS_PIN_DIGITAL(pin))
+ servos[servoPinMap[pin]].write(value);
+ Firmata.setPinState(pin, value);
+ break;
+ case PIN_MODE_PWM:
+ if (IS_PIN_PWM(pin))
+ analogWrite(PIN_TO_PWM(pin), value);
+ Firmata.setPinState(pin, value);
+ break;
+ }
+ }
+}
+
+void digitalWriteCallback(byte port, int value)
+{
+ byte pin, lastPin, pinValue, mask = 1, pinWriteMask = 0;
+
+ if (port < TOTAL_PORTS) {
+ // create a mask of the pins on this port that are writable.
+ lastPin = port * 8 + 8;
+ if (lastPin > TOTAL_PINS) lastPin = TOTAL_PINS;
+ for (pin = port * 8; pin < lastPin; pin++) {
+ // do not disturb non-digital pins (eg, Rx & Tx)
+ if (IS_PIN_DIGITAL(pin)) {
+ // do not touch pins in PWM, ANALOG, SERVO or other modes
+ if (Firmata.getPinMode(pin) == OUTPUT || Firmata.getPinMode(pin) == INPUT) {
+ pinValue = ((byte)value & mask) ? 1 : 0;
+ if (Firmata.getPinMode(pin) == OUTPUT) {
+ pinWriteMask |= mask;
+ } else if (Firmata.getPinMode(pin) == INPUT && pinValue == 1 && Firmata.getPinState(pin) != 1) {
+ // only handle INPUT here for backwards compatibility
+#if ARDUINO > 100
+ pinMode(pin, INPUT_PULLUP);
+#else
+ // only write to the INPUT pin to enable pullups if Arduino v1.0.0 or earlier
+ pinWriteMask |= mask;
+#endif
+ }
+ Firmata.setPinState(pin, pinValue);
+ }
+ }
+ mask = mask << 1;
+ }
+ writePort(port, (byte)value, pinWriteMask);
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+/* sets bits in a bit array (int) to toggle the reporting of the analogIns
+ */
+//void FirmataClass::setAnalogPinReporting(byte pin, byte state) {
+//}
+void reportAnalogCallback(byte analogPin, int value)
+{
+ if (analogPin < TOTAL_ANALOG_PINS) {
+ if (value == 0) {
+ analogInputsToReport = analogInputsToReport & ~ (1 << analogPin);
+ } else {
+ analogInputsToReport = analogInputsToReport | (1 << analogPin);
+ // prevent during system reset or all analog pin values will be reported
+ // which may report noise for unconnected analog pins
+ if (!isResetting) {
+ // Send pin value immediately. This is helpful when connected via
+ // ethernet, wi-fi or bluetooth so pin states can be known upon
+ // reconnecting.
+ Firmata.sendAnalog(analogPin, analogRead(analogPin));
+ }
+ }
+ }
+ // TODO: save status to EEPROM here, if changed
+}
+
+void reportDigitalCallback(byte port, int value)
+{
+ if (port < TOTAL_PORTS) {
+ reportPINs[port] = (byte)value;
+ // Send port value immediately. This is helpful when connected via
+ // ethernet, wi-fi or bluetooth so pin states can be known upon
+ // reconnecting.
+ if (value) outputPort(port, readPort(port, portConfigInputs[port]), true);
+ }
+ // do not disable analog reporting on these 8 pins, to allow some
+ // pins used for digital, others analog. Instead, allow both types
+ // of reporting to be enabled, but check if the pin is configured
+ // as analog when sampling the analog inputs. Likewise, while
+ // scanning digital pins, portConfigInputs will mask off values from any
+ // pins configured as analog
+}
+
+/*==============================================================================
+ * SYSEX-BASED commands
+ *============================================================================*/
+
+void sysexCallback(byte command, byte argc, byte *argv)
+{
+ byte mode;
+ byte stopTX;
+ byte slaveAddress;
+ byte data;
+ int slaveRegister;
+ unsigned int delayTime;
+
+ switch (command) {
+ case I2C_REQUEST:
+ mode = argv[1] & I2C_READ_WRITE_MODE_MASK;
+ if (argv[1] & I2C_10BIT_ADDRESS_MODE_MASK) {
+ Firmata.sendString("10-bit addressing not supported");
+ return;
+ }
+ else {
+ slaveAddress = argv[0];
+ }
+
+ // need to invert the logic here since 0 will be default for client
+ // libraries that have not updated to add support for restart tx
+ if (argv[1] & I2C_END_TX_MASK) {
+ stopTX = I2C_RESTART_TX;
+ }
+ else {
+ stopTX = I2C_STOP_TX; // default
+ }
+
+ switch (mode) {
+ case I2C_WRITE:
+ Wire.beginTransmission(slaveAddress);
+ for (byte i = 2; i < argc; i += 2) {
+ data = argv[i] + (argv[i + 1] << 7);
+ wireWrite(data);
+ }
+ Wire.endTransmission();
+ delayMicroseconds(70);
+ break;
+ case I2C_READ:
+ if (argc == 6) {
+ // a slave register is specified
+ slaveRegister = argv[2] + (argv[3] << 7);
+ data = argv[4] + (argv[5] << 7); // bytes to read
+ }
+ else {
+ // a slave register is NOT specified
+ slaveRegister = I2C_REGISTER_NOT_SPECIFIED;
+ data = argv[2] + (argv[3] << 7); // bytes to read
+ }
+ readAndReportData(slaveAddress, (int)slaveRegister, data, stopTX);
+ break;
+ case I2C_READ_CONTINUOUSLY:
+ if ((queryIndex + 1) >= I2C_MAX_QUERIES) {
+ // too many queries, just ignore
+ Firmata.sendString("too many queries");
+ break;
+ }
+ if (argc == 6) {
+ // a slave register is specified
+ slaveRegister = argv[2] + (argv[3] << 7);
+ data = argv[4] + (argv[5] << 7); // bytes to read
+ }
+ else {
+ // a slave register is NOT specified
+ slaveRegister = (int)I2C_REGISTER_NOT_SPECIFIED;
+ data = argv[2] + (argv[3] << 7); // bytes to read
+ }
+ queryIndex++;
+ query[queryIndex].addr = slaveAddress;
+ query[queryIndex].reg = slaveRegister;
+ query[queryIndex].bytes = data;
+ query[queryIndex].stopTX = stopTX;
+ break;
+ case I2C_STOP_READING:
+ byte queryIndexToSkip;
+ // if read continuous mode is enabled for only 1 i2c device, disable
+ // read continuous reporting for that device
+ if (queryIndex <= 0) {
+ queryIndex = -1;
+ } else {
+ queryIndexToSkip = 0;
+ // if read continuous mode is enabled for multiple devices,
+ // determine which device to stop reading and remove it's data from
+ // the array, shifiting other array data to fill the space
+ for (byte i = 0; i < queryIndex + 1; i++) {
+ if (query[i].addr == slaveAddress) {
+ queryIndexToSkip = i;
+ break;
+ }
+ }
+
+ for (byte i = queryIndexToSkip; i < queryIndex + 1; i++) {
+ if (i < I2C_MAX_QUERIES) {
+ query[i].addr = query[i + 1].addr;
+ query[i].reg = query[i + 1].reg;
+ query[i].bytes = query[i + 1].bytes;
+ query[i].stopTX = query[i + 1].stopTX;
+ }
+ }
+ queryIndex--;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case I2C_CONFIG:
+ delayTime = (argv[0] + (argv[1] << 7));
+
+ if (argc > 1 && delayTime > 0) {
+ i2cReadDelayTime = delayTime;
+ }
+
+ if (!isI2CEnabled) {
+ enableI2CPins();
+ }
+
+ break;
+ case SERVO_CONFIG:
+ if (argc > 4) {
+ // these vars are here for clarity, they'll optimized away by the compiler
+ byte pin = argv[0];
+ int minPulse = argv[1] + (argv[2] << 7);
+ int maxPulse = argv[3] + (argv[4] << 7);
+
+ if (IS_PIN_DIGITAL(pin)) {
+ if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) {
+ detachServo(pin);
+ }
+ attachServo(pin, minPulse, maxPulse);
+ setPinModeCallback(pin, PIN_MODE_SERVO);
+ }
+ }
+ break;
+ case SAMPLING_INTERVAL:
+ if (argc > 1) {
+ samplingInterval = argv[0] + (argv[1] << 7);
+ if (samplingInterval < MINIMUM_SAMPLING_INTERVAL) {
+ samplingInterval = MINIMUM_SAMPLING_INTERVAL;
+ }
+ } else {
+ //Firmata.sendString("Not enough data");
+ }
+ break;
+ case EXTENDED_ANALOG:
+ if (argc > 1) {
+ int val = argv[1];
+ if (argc > 2) val |= (argv[2] << 7);
+ if (argc > 3) val |= (argv[3] << 14);
+ analogWriteCallback(argv[0], val);
+ }
+ break;
+ case CAPABILITY_QUERY:
+ Firmata.write(START_SYSEX);
+ Firmata.write(CAPABILITY_RESPONSE);
+ for (byte pin = 0; pin < TOTAL_PINS; pin++) {
+ if (IS_PIN_DIGITAL(pin)) {
+ Firmata.write((byte)INPUT);
+ Firmata.write(1);
+ Firmata.write((byte)PIN_MODE_PULLUP);
+ Firmata.write(1);
+ Firmata.write((byte)OUTPUT);
+ Firmata.write(1);
+ }
+ if (IS_PIN_ANALOG(pin)) {
+ Firmata.write(PIN_MODE_ANALOG);
+ Firmata.write(10); // 10 = 10-bit resolution
+ }
+ if (IS_PIN_PWM(pin)) {
+ Firmata.write(PIN_MODE_PWM);
+ Firmata.write(8); // 8 = 8-bit resolution
+ }
+ if (IS_PIN_DIGITAL(pin)) {
+ Firmata.write(PIN_MODE_SERVO);
+ Firmata.write(14);
+ }
+ if (IS_PIN_I2C(pin)) {
+ Firmata.write(PIN_MODE_I2C);
+ Firmata.write(1); // TODO: could assign a number to map to SCL or SDA
+ }
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.handleCapability(pin);
+#endif
+ Firmata.write(127);
+ }
+ Firmata.write(END_SYSEX);
+ break;
+ case PIN_STATE_QUERY:
+ if (argc > 0) {
+ byte pin = argv[0];
+ Firmata.write(START_SYSEX);
+ Firmata.write(PIN_STATE_RESPONSE);
+ Firmata.write(pin);
+ if (pin < TOTAL_PINS) {
+ Firmata.write(Firmata.getPinMode(pin));
+ Firmata.write((byte)Firmata.getPinState(pin) & 0x7F);
+ if (Firmata.getPinState(pin) & 0xFF80) Firmata.write((byte)(Firmata.getPinState(pin) >> 7) & 0x7F);
+ if (Firmata.getPinState(pin) & 0xC000) Firmata.write((byte)(Firmata.getPinState(pin) >> 14) & 0x7F);
+ }
+ Firmata.write(END_SYSEX);
+ }
+ break;
+ case ANALOG_MAPPING_QUERY:
+ Firmata.write(START_SYSEX);
+ Firmata.write(ANALOG_MAPPING_RESPONSE);
+ for (byte pin = 0; pin < TOTAL_PINS; pin++) {
+ Firmata.write(IS_PIN_ANALOG(pin) ? PIN_TO_ANALOG(pin) : 127);
+ }
+ Firmata.write(END_SYSEX);
+ break;
+
+ case SERIAL_MESSAGE:
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.handleSysex(command, argc, argv);
+#endif
+ break;
+ }
+}
+
+/*==============================================================================
+ * SETUP()
+ *============================================================================*/
+
+void systemResetCallback()
+{
+ isResetting = true;
+
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.reset();
+#endif
+
+ if (isI2CEnabled) {
+ disableI2CPins();
+ }
+
+ for (byte i = 0; i < TOTAL_PORTS; i++) {
+ reportPINs[i] = false; // by default, reporting off
+ portConfigInputs[i] = 0; // until activated
+ previousPINs[i] = 0;
+ }
+
+ for (byte i = 0; i < TOTAL_PINS; i++) {
+ // pins with analog capability default to analog input
+ // otherwise, pins default to digital output
+ if (IS_PIN_ANALOG(i)) {
+ // turns off pullup, configures everything
+ setPinModeCallback(i, PIN_MODE_ANALOG);
+ } else if (IS_PIN_DIGITAL(i)) {
+ // sets the output to 0, configures portConfigInputs
+ setPinModeCallback(i, OUTPUT);
+ }
+
+ servoPinMap[i] = 255;
+ }
+ // by default, do not report any analog inputs
+ analogInputsToReport = 0;
+
+ detachedServoCount = 0;
+ servoCount = 0;
+
+ isResetting = false;
+}
+
+void setup()
+{
+ DEBUG_BEGIN(9600);
+
+ Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
+
+ Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
+ Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
+ Firmata.attach(REPORT_ANALOG, reportAnalogCallback);
+ Firmata.attach(REPORT_DIGITAL, reportDigitalCallback);
+ Firmata.attach(SET_PIN_MODE, setPinModeCallback);
+ Firmata.attach(SET_DIGITAL_PIN_VALUE, setPinValueCallback);
+ Firmata.attach(START_SYSEX, sysexCallback);
+ Firmata.attach(SYSTEM_RESET, systemResetCallback);
+
+ stream.setLocalName(FIRMATA_BLE_LOCAL_NAME);
+
+ // set the BLE connection interval - this is the fastest interval you can read inputs
+ stream.setConnectionInterval(FIRMATA_BLE_MIN_INTERVAL, FIRMATA_BLE_MAX_INTERVAL);
+ // set how often the BLE TX buffer is flushed (if not full)
+ stream.setFlushInterval(FIRMATA_BLE_MAX_INTERVAL);
+
+#ifdef BLE_REQ
+ for (byte i = 0; i < TOTAL_PINS; i++) {
+ if (IS_IGNORE_BLE_PINS(i)) {
+ Firmata.setPinMode(i, PIN_MODE_IGNORE);
+ }
+ }
+#endif
+
+ stream.begin();
+ Firmata.begin(stream);
+
+ systemResetCallback(); // reset to default config
+}
+
+/*==============================================================================
+ * LOOP()
+ *============================================================================*/
+void loop()
+{
+ byte pin, analogPin;
+
+ // do not process data if no BLE connection is established
+ // poll will send the TX buffer at the specified flush interval or when the buffer is full
+ if (!stream.poll()) return;
+
+ /* DIGITALREAD - as fast as possible, check for changes and output them to the
+ * Stream buffer using Stream.write() */
+ checkDigitalInputs();
+
+ /* STREAMREAD - processing incoming messagse as soon as possible, while still
+ * checking digital inputs. */
+ while (Firmata.available())
+ Firmata.processInput();
+
+ currentMillis = millis();
+ if (currentMillis - previousMillis > samplingInterval) {
+ previousMillis = currentMillis;
+ /* ANALOGREAD - do all analogReads() at the configured sampling interval */
+ for (pin = 0; pin < TOTAL_PINS; pin++) {
+ if (IS_PIN_ANALOG(pin) && Firmata.getPinMode(pin) == PIN_MODE_ANALOG) {
+ analogPin = PIN_TO_ANALOG(pin);
+ if (analogInputsToReport & (1 << analogPin)) {
+ Firmata.sendAnalog(analogPin, analogRead(analogPin));
+ }
+ }
+ }
+ // report i2c data for all device with read continuous mode enabled
+ if (queryIndex > -1) {
+ for (byte i = 0; i < queryIndex + 1; i++) {
+ readAndReportData(query[i].addr, query[i].reg, query[i].bytes, query[i].stopTX);
+ }
+ }
+ }
+
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.update();
+#endif
+}
--- /dev/null
+/*==================================================================================================
+ * BLE CONFIGURATION
+ *
+ * If you are using an Arduino 101, you do not need to make any changes to this file (unless you
+ * need a unique ble local name (see below). If you are using another supported BLE board or shield,
+ * follow the instructions for the specific board or shield below.
+ *
+ * Make sure you have the Intel Curie Boards package v1.0.6 or higher installed via the Arduino
+ * Boards Manager.
+ *
+ * Supported boards and shields:
+ * - Arduino 101 (recommended)
+ * - RedBearLab BLE Shield (v2) ** to be verified **
+ * - RedBearLab BLE Nano ** works with modifications **
+ *
+ *================================================================================================*/
+
+// change this to a unique name per board if running StandardFirmataBLE on multiple boards
+// within the same physical space
+#define FIRMATA_BLE_LOCAL_NAME "FIRMATA"
+
+/*
+ * RedBearLab BLE Shield
+ *
+ * If you are using a RedBearLab BLE shield, uncomment the define below.
+ * Also, change the define for BLE_RST if you have the jumper set to pin 7 rather than pin 4.
+ *
+ * You will need to use the shield with an Arduino Zero, Due, Mega, or other board with sufficient
+ * Flash and RAM. Arduino Uno, Leonardo and other ATmega328p and Atmega32u4 boards to not have
+ * enough memory to run StandardFirmataBLE.
+ *
+ * TODO: verify if this works and with which boards it works.
+ *
+ * Test script: https://gist.github.com/soundanalogous/927360b797574ed50e27
+ */
+//#define REDBEAR_BLE_SHIELD
+
+#ifdef REDBEAR_BLE_SHIELD
+#include <SPI.h>
+#include <BLEPeripheral.h>
+#include "utility/BLEStream.h"
+
+#define BLE_REQ 9
+#define BLE_RDY 8
+#define BLE_RST 4 // 4 or 7 via jumper on shield
+
+BLEStream stream(BLE_REQ, BLE_RDY, BLE_RST);
+#endif
+
+
+/*==================================================================================================
+ * END BLE CONFIGURATION - you should not need to change anything below this line
+ *================================================================================================*/
+
+/*
+ * Arduino 101
+ *
+ * Make sure you have the Intel Curie Boards package v1.0.6 or higher installed via the Arduino
+ * Boards Manager.
+ *
+ * Test script: https://gist.github.com/soundanalogous/927360b797574ed50e27
+ */
+#ifdef _VARIANT_ARDUINO_101_X_
+#include <CurieBLE.h>
+#include "utility/BLEStream.h"
+BLEStream stream;
+#endif
+
+
+/*
+ * RedBearLab BLE Nano (with default switch settings)
+ *
+ * Blocked on this issue: https://github.com/RedBearLab/nRF51822-Arduino/issues/46
+ * Works with modifications. See comments at top of the test script referenced below.
+ * When the RBL nRF51822-Arduino library issue is resolved, this should work witout
+ * any modifications.
+ *
+ * Test script: https://gist.github.com/soundanalogous/d39bb3eb36333a0906df
+ *
+ * Note: If you have changed the solder jumpers on the Nano you may encounter issues since
+ * the pins are currently mapped in Firmata only for the default (factory) jumper settings.
+ */
+// #ifdef BLE_NANO
+// #include <BLEPeripheral.h>
+// #include "utility/BLEStream.h"
+// BLEStream stream;
+// #endif
+
+
+/*
+ * RedBearLab Blend and Blend Micro
+ *
+ * StandardFirmataBLE requires too much Flash and RAM to run on the ATmega32u4-based Blend
+ * and Blend Micro boards. It may work with ConfigurableFirmata selecting only analog and/or
+ * digital I/O.
+ */
+// #if defined(BLEND_MICRO) || defined(BLEND)
+// #include <SPI.h>
+// #include <BLEPeripheral.h>
+// #include "utility/BLEStream.h"
+
+// #define BLE_REQ 6
+// #define BLE_RDY 7
+// #define BLE_RST 4
+
+// BLEStream stream(BLE_REQ, BLE_RDY, BLE_RST);
+// #endif
+
+
+#if defined(BLE_REQ) && defined(BLE_RDY) && defined(BLE_RST)
+#define IS_IGNORE_BLE_PINS(p) ((p) == BLE_REQ || (p) == BLE_RDY || (p) == BLE_RST)
+#endif
--- /dev/null
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+\f
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
--- /dev/null
+/*
+ Firmata is a generic protocol for communicating with microcontrollers
+ from software on a host computer. It is intended to work with
+ any host computer software package.
+
+ To download a host software package, please click on the following link
+ to open the list of Firmata client libraries in your default browser.
+
+ https://github.com/firmata/arduino#firmata-client-libraries
+
+ Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.
+ Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved.
+ Copyright (C) 2009 Shigeru Kobayashi. All rights reserved.
+ Copyright (C) 2009-2016 Jeff Hoefs. All rights reserved.
+ Copyright (C) 2015 Brian Schmalz. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+
+ Last updated August 17th, 2017
+*/
+
+#include <SoftPWMServo.h> // Gives us PWM and Servo on every pin
+#include <Wire.h>
+#include <Firmata.h>
+
+#define I2C_WRITE B00000000
+#define I2C_READ B00001000
+#define I2C_READ_CONTINUOUSLY B00010000
+#define I2C_STOP_READING B00011000
+#define I2C_READ_WRITE_MODE_MASK B00011000
+#define I2C_10BIT_ADDRESS_MODE_MASK B00100000
+#define I2C_END_TX_MASK B01000000
+#define I2C_STOP_TX 1
+#define I2C_RESTART_TX 0
+#define I2C_MAX_QUERIES 8
+#define I2C_REGISTER_NOT_SPECIFIED -1
+
+// the minimum interval for sampling analog input
+#define MINIMUM_SAMPLING_INTERVAL 1
+
+
+/*==============================================================================
+ * GLOBAL VARIABLES
+ *============================================================================*/
+
+/* analog inputs */
+int analogInputsToReport = 0; // bitwise array to store pin reporting
+
+/* digital input ports */
+byte reportPINs[TOTAL_PORTS]; // 1 = report this port, 0 = silence
+byte previousPINs[TOTAL_PORTS]; // previous 8 bits sent
+
+/* pins configuration */
+byte portConfigInputs[TOTAL_PORTS]; // each bit: 1 = pin in INPUT, 0 = anything else
+
+/* timer variables */
+unsigned long currentMillis; // store the current value from millis()
+unsigned long previousMillis; // for comparison with currentMillis
+unsigned int samplingInterval = 19; // how often to run the main loop (in ms)
+
+/* i2c data */
+struct i2c_device_info {
+ byte addr;
+ int reg;
+ byte bytes;
+ byte stopTX;
+};
+
+/* for i2c read continuous more */
+i2c_device_info query[I2C_MAX_QUERIES];
+
+byte i2cRxData[64];
+boolean isI2CEnabled = false;
+signed char queryIndex = -1;
+// default delay time between i2c read request and Wire.requestFrom()
+unsigned int i2cReadDelayTime = 0;
+
+SoftServo servos[MAX_SERVOS];
+byte servoPinMap[TOTAL_PINS];
+byte detachedServos[MAX_SERVOS];
+byte detachedServoCount = 0;
+byte servoCount = 0;
+
+boolean isResetting = false;
+
+// Forward declare a few functions to avoid compiler errors with older versions
+// of the Arduino IDE.
+void setPinModeCallback(byte, int);
+void reportAnalogCallback(byte analogPin, int value);
+void sysexCallback(byte, byte, byte*);
+
+/* utility functions */
+void wireWrite(byte data)
+{
+#if ARDUINO >= 100
+ Wire.write((byte)data);
+#else
+ Wire.send(data);
+#endif
+}
+
+byte wireRead(void)
+{
+#if ARDUINO >= 100
+ return Wire.read();
+#else
+ return Wire.receive();
+#endif
+}
+
+/*==============================================================================
+ * FUNCTIONS
+ *============================================================================*/
+
+void attachServo(byte pin, int minPulse, int maxPulse)
+{
+ if (servoCount < MAX_SERVOS) {
+ // reuse indexes of detached servos until all have been reallocated
+ if (detachedServoCount > 0) {
+ servoPinMap[pin] = detachedServos[detachedServoCount - 1];
+ if (detachedServoCount > 0) detachedServoCount--;
+ } else {
+ servoPinMap[pin] = servoCount;
+ servoCount++;
+ }
+ if (minPulse > 0 && maxPulse > 0) {
+ servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin), minPulse, maxPulse);
+ } else {
+ servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin));
+ }
+ } else {
+ Firmata.sendString("Max servos attached");
+ }
+}
+
+void detachServo(byte pin)
+{
+ servos[servoPinMap[pin]].detach();
+ // if we're detaching the last servo, decrement the count
+ // otherwise store the index of the detached servo
+ if (servoPinMap[pin] == servoCount && servoCount > 0) {
+ servoCount--;
+ } else if (servoCount > 0) {
+ // keep track of detached servos because we want to reuse their indexes
+ // before incrementing the count of attached servos
+ detachedServoCount++;
+ detachedServos[detachedServoCount - 1] = servoPinMap[pin];
+ }
+
+ servoPinMap[pin] = 255;
+}
+
+void enableI2CPins()
+{
+ byte i;
+ // is there a faster way to do this? would probaby require importing
+ // Arduino.h to get SCL and SDA pins
+ for (i = 0; i < TOTAL_PINS; i++) {
+ if (IS_PIN_I2C(i)) {
+ // mark pins as i2c so they are ignore in non i2c data requests
+ setPinModeCallback(i, PIN_MODE_I2C);
+ }
+ }
+
+ isI2CEnabled = true;
+
+ Wire.begin();
+}
+
+/* disable the i2c pins so they can be used for other functions */
+void disableI2CPins() {
+ isI2CEnabled = false;
+ // disable read continuous mode for all devices
+ queryIndex = -1;
+}
+
+void readAndReportData(byte address, int theRegister, byte numBytes, byte stopTX) {
+ // allow I2C requests that don't require a register read
+ // for example, some devices using an interrupt pin to signify new data available
+ // do not always require the register read so upon interrupt you call Wire.requestFrom()
+ if (theRegister != I2C_REGISTER_NOT_SPECIFIED) {
+ Wire.beginTransmission(address);
+ wireWrite((byte)theRegister);
+ Wire.endTransmission(stopTX); // default = true
+ // do not set a value of 0
+ if (i2cReadDelayTime > 0) {
+ // delay is necessary for some devices such as WiiNunchuck
+ delayMicroseconds(i2cReadDelayTime);
+ }
+ } else {
+ theRegister = 0; // fill the register with a dummy value
+ }
+
+ Wire.requestFrom(address, numBytes); // all bytes are returned in requestFrom
+
+ // check to be sure correct number of bytes were returned by slave
+ if (numBytes < Wire.available()) {
+ Firmata.sendString("I2C: Too many bytes received");
+ } else if (numBytes > Wire.available()) {
+ Firmata.sendString("I2C: Too few bytes received");
+ }
+
+ i2cRxData[0] = address;
+ i2cRxData[1] = theRegister;
+
+ for (int i = 0; i < numBytes && Wire.available(); i++) {
+ i2cRxData[2 + i] = wireRead();
+ }
+
+ // send slave address, register and received bytes
+ Firmata.sendSysex(SYSEX_I2C_REPLY, numBytes + 2, i2cRxData);
+}
+
+void outputPort(byte portNumber, byte portValue, byte forceSend)
+{
+ // pins not configured as INPUT are cleared to zeros
+ portValue = portValue & portConfigInputs[portNumber];
+ // only send if the value is different than previously sent
+ if (forceSend || previousPINs[portNumber] != portValue) {
+ Firmata.sendDigitalPort(portNumber, portValue);
+ previousPINs[portNumber] = portValue;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * check all the active digital inputs for change of state, then add any events
+ * to the Serial output queue using Serial.print() */
+void checkDigitalInputs(void)
+{
+ /* Using non-looping code allows constants to be given to readPort().
+ * The compiler will apply substantial optimizations if the inputs
+ * to readPort() are compile-time constants. */
+ if (TOTAL_PORTS > 0 && reportPINs[0]) outputPort(0, readPort(0, portConfigInputs[0]), false);
+ if (TOTAL_PORTS > 1 && reportPINs[1]) outputPort(1, readPort(1, portConfigInputs[1]), false);
+ if (TOTAL_PORTS > 2 && reportPINs[2]) outputPort(2, readPort(2, portConfigInputs[2]), false);
+ if (TOTAL_PORTS > 3 && reportPINs[3]) outputPort(3, readPort(3, portConfigInputs[3]), false);
+ if (TOTAL_PORTS > 4 && reportPINs[4]) outputPort(4, readPort(4, portConfigInputs[4]), false);
+ if (TOTAL_PORTS > 5 && reportPINs[5]) outputPort(5, readPort(5, portConfigInputs[5]), false);
+ if (TOTAL_PORTS > 6 && reportPINs[6]) outputPort(6, readPort(6, portConfigInputs[6]), false);
+ if (TOTAL_PORTS > 7 && reportPINs[7]) outputPort(7, readPort(7, portConfigInputs[7]), false);
+ if (TOTAL_PORTS > 8 && reportPINs[8]) outputPort(8, readPort(8, portConfigInputs[8]), false);
+ if (TOTAL_PORTS > 9 && reportPINs[9]) outputPort(9, readPort(9, portConfigInputs[9]), false);
+ if (TOTAL_PORTS > 10 && reportPINs[10]) outputPort(10, readPort(10, portConfigInputs[10]), false);
+ if (TOTAL_PORTS > 11 && reportPINs[11]) outputPort(11, readPort(11, portConfigInputs[11]), false);
+ if (TOTAL_PORTS > 12 && reportPINs[12]) outputPort(12, readPort(12, portConfigInputs[12]), false);
+ if (TOTAL_PORTS > 13 && reportPINs[13]) outputPort(13, readPort(13, portConfigInputs[13]), false);
+ if (TOTAL_PORTS > 14 && reportPINs[14]) outputPort(14, readPort(14, portConfigInputs[14]), false);
+ if (TOTAL_PORTS > 15 && reportPINs[15]) outputPort(15, readPort(15, portConfigInputs[15]), false);
+}
+
+// -----------------------------------------------------------------------------
+/* Sets a pin that is in Servo mode to a particular output value
+ * (i.e. pulse width). Different boards may have different ways of
+ * setting servo values, so putting it in a function keeps things cleaner.
+ */
+void servoWrite(byte pin, int value)
+{
+ SoftPWMServoPWMWrite(PIN_TO_PWM(pin), value);
+}
+
+// -----------------------------------------------------------------------------
+/* sets the pin mode to the correct state and sets the relevant bits in the
+ * two bit-arrays that track Digital I/O and PWM status
+ */
+void setPinModeCallback(byte pin, int mode)
+{
+ if (Firmata.getPinMode(pin) == PIN_MODE_IGNORE)
+ return;
+
+ if (Firmata.getPinMode(pin) == PIN_MODE_I2C && isI2CEnabled && mode != PIN_MODE_I2C) {
+ // disable i2c so pins can be used for other functions
+ // the following if statements should reconfigure the pins properly
+ disableI2CPins();
+ }
+ if (IS_PIN_DIGITAL(pin) && mode != PIN_MODE_SERVO) {
+ if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) {
+ detachServo(pin);
+ }
+ }
+ if (IS_PIN_ANALOG(pin)) {
+ reportAnalogCallback(PIN_TO_ANALOG(pin), mode == PIN_MODE_ANALOG ? 1 : 0); // turn on/off reporting
+ }
+ if (IS_PIN_DIGITAL(pin)) {
+ if (mode == INPUT || mode == PIN_MODE_PULLUP) {
+ portConfigInputs[pin / 8] |= (1 << (pin & 7));
+ } else {
+ portConfigInputs[pin / 8] &= ~(1 << (pin & 7));
+ }
+ }
+ Firmata.setPinState(pin, 0);
+ switch (mode) {
+ case PIN_MODE_ANALOG:
+ if (IS_PIN_ANALOG(pin)) {
+ if (IS_PIN_DIGITAL(pin)) {
+ pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
+#if ARDUINO <= 100
+ // deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6
+ digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
+#endif
+ }
+ Firmata.setPinMode(pin, PIN_MODE_ANALOG);
+ }
+ break;
+ case INPUT:
+ if (IS_PIN_DIGITAL(pin)) {
+ pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
+#if ARDUINO <= 100
+ // deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6
+ digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
+#endif
+ Firmata.setPinMode(pin, INPUT);
+ }
+ break;
+ case PIN_MODE_PULLUP:
+ if (IS_PIN_DIGITAL(pin)) {
+ pinMode(PIN_TO_DIGITAL(pin), INPUT_PULLUP);
+ Firmata.setPinMode(pin, PIN_MODE_PULLUP);
+ Firmata.setPinState(pin, 1);
+ }
+ break;
+ case OUTPUT:
+ if (IS_PIN_DIGITAL(pin)) {
+ if (Firmata.getPinMode(pin) == PIN_MODE_PWM) {
+ // Disable PWM if pin mode was previously set to PWM.
+ digitalWrite(PIN_TO_DIGITAL(pin), LOW);
+ }
+ pinMode(PIN_TO_DIGITAL(pin), OUTPUT);
+ Firmata.setPinMode(pin, OUTPUT);
+ }
+ break;
+ case PIN_MODE_PWM:
+ if (IS_PIN_PWM(pin)) {
+ pinMode(PIN_TO_PWM(pin), OUTPUT);
+ servoWrite(PIN_TO_PWM(pin), 0);
+ Firmata.setPinMode(pin, PIN_MODE_PWM);
+ }
+ break;
+ case PIN_MODE_SERVO:
+ if (IS_PIN_DIGITAL(pin)) {
+ Firmata.setPinMode(pin, PIN_MODE_SERVO);
+ if (servoPinMap[pin] == 255 || !servos[servoPinMap[pin]].attached()) {
+ // pass -1 for min and max pulse values to use default values set
+ // by Servo library
+ attachServo(pin, -1, -1);
+ }
+ }
+ break;
+ case PIN_MODE_I2C:
+ if (IS_PIN_I2C(pin)) {
+ // mark the pin as i2c
+ // the user must call I2C_CONFIG to enable I2C for a device
+ Firmata.setPinMode(pin, PIN_MODE_I2C);
+ }
+ break;
+ default:
+ Firmata.sendString("Unknown pin mode"); // TODO: put error msgs in EEPROM
+ }
+ // TODO: save status to EEPROM here, if changed
+}
+
+/*
+ * Sets the value of an individual pin. Useful if you want to set a pin value but
+ * are not tracking the digital port state.
+ * Can only be used on pins configured as OUTPUT.
+ * Cannot be used to enable pull-ups on Digital INPUT pins.
+ */
+void setPinValueCallback(byte pin, int value)
+{
+ if (pin < TOTAL_PINS && IS_PIN_DIGITAL(pin)) {
+ if (Firmata.getPinMode(pin) == OUTPUT) {
+ Firmata.setPinState(pin, value);
+ digitalWrite(PIN_TO_DIGITAL(pin), value);
+ }
+ }
+}
+
+void analogWriteCallback(byte pin, int value)
+{
+ if (pin < TOTAL_PINS) {
+ switch (Firmata.getPinMode(pin)) {
+ case PIN_MODE_SERVO:
+ if (IS_PIN_DIGITAL(pin))
+ servos[servoPinMap[pin]].write(value);
+ Firmata.setPinState(pin, value);
+ break;
+ case PIN_MODE_PWM:
+ if (IS_PIN_PWM(pin))
+ servoWrite(PIN_TO_PWM(pin), value);
+ Firmata.setPinState(pin, value);
+ break;
+ }
+ }
+}
+
+void digitalWriteCallback(byte port, int value)
+{
+ byte pin, lastPin, pinValue, mask = 1, pinWriteMask = 0;
+
+ if (port < TOTAL_PORTS) {
+ // create a mask of the pins on this port that are writable.
+ lastPin = port * 8 + 8;
+ if (lastPin > TOTAL_PINS) lastPin = TOTAL_PINS;
+ for (pin = port * 8; pin < lastPin; pin++) {
+ // do not disturb non-digital pins (eg, Rx & Tx)
+ if (IS_PIN_DIGITAL(pin)) {
+ // do not touch pins in PWM, ANALOG, SERVO or other modes
+ if (Firmata.getPinMode(pin) == OUTPUT || Firmata.getPinMode(pin) == INPUT) {
+ pinValue = ((byte)value & mask) ? 1 : 0;
+ if (Firmata.getPinMode(pin) == OUTPUT) {
+ pinWriteMask |= mask;
+ } else if (Firmata.getPinMode(pin) == INPUT && pinValue == 1 && Firmata.getPinState(pin) != 1) {
+ // only handle INPUT here for backwards compatibility
+#if ARDUINO > 100
+ pinMode(pin, INPUT_PULLUP);
+#else
+ // only write to the INPUT pin to enable pullups if Arduino v1.0.0 or earlier
+ pinWriteMask |= mask;
+#endif
+ }
+ Firmata.setPinState(pin, pinValue);
+ }
+ }
+ mask = mask << 1;
+ }
+ writePort(port, (byte)value, pinWriteMask);
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+/* sets bits in a bit array (int) to toggle the reporting of the analogIns
+ */
+//void FirmataClass::setAnalogPinReporting(byte pin, byte state) {
+//}
+void reportAnalogCallback(byte analogPin, int value)
+{
+ if (analogPin < TOTAL_ANALOG_PINS) {
+ if (value == 0) {
+ analogInputsToReport = analogInputsToReport & ~ (1 << analogPin);
+ } else {
+ analogInputsToReport = analogInputsToReport | (1 << analogPin);
+ // prevent during system reset or all analog pin values will be reported
+ // which may report noise for unconnected analog pins
+ if (!isResetting) {
+ // Send pin value immediately. This is helpful when connected via
+ // ethernet, wi-fi or bluetooth so pin states can be known upon
+ // reconnecting.
+ Firmata.sendAnalog(analogPin, analogRead(analogPin));
+ }
+ }
+ }
+ // TODO: save status to EEPROM here, if changed
+}
+
+void reportDigitalCallback(byte port, int value)
+{
+ if (port < TOTAL_PORTS) {
+ reportPINs[port] = (byte)value;
+ // Send port value immediately. This is helpful when connected via
+ // ethernet, wi-fi or bluetooth so pin states can be known upon
+ // reconnecting.
+ if (value) outputPort(port, readPort(port, portConfigInputs[port]), true);
+ }
+ // do not disable analog reporting on these 8 pins, to allow some
+ // pins used for digital, others analog. Instead, allow both types
+ // of reporting to be enabled, but check if the pin is configured
+ // as analog when sampling the analog inputs. Likewise, while
+ // scanning digital pins, portConfigInputs will mask off values from any
+ // pins configured as analog
+}
+
+/*==============================================================================
+ * SYSEX-BASED commands
+ *============================================================================*/
+
+void sysexCallback(byte command, byte argc, byte *argv)
+{
+ byte mode;
+ byte stopTX;
+ byte slaveAddress;
+ byte data;
+ int slaveRegister;
+ unsigned int delayTime;
+
+ switch (command) {
+ case I2C_REQUEST:
+ mode = argv[1] & I2C_READ_WRITE_MODE_MASK;
+ if (argv[1] & I2C_10BIT_ADDRESS_MODE_MASK) {
+ Firmata.sendString("10-bit addressing not supported");
+ return;
+ }
+ else {
+ slaveAddress = argv[0];
+ }
+
+ // need to invert the logic here since 0 will be default for client
+ // libraries that have not updated to add support for restart tx
+ if (argv[1] & I2C_END_TX_MASK) {
+ stopTX = I2C_RESTART_TX;
+ }
+ else {
+ stopTX = I2C_STOP_TX; // default
+ }
+
+ switch (mode) {
+ case I2C_WRITE:
+ Wire.beginTransmission(slaveAddress);
+ for (byte i = 2; i < argc; i += 2) {
+ data = argv[i] + (argv[i + 1] << 7);
+ wireWrite(data);
+ }
+ Wire.endTransmission();
+ delayMicroseconds(70);
+ break;
+ case I2C_READ:
+ if (argc == 6) {
+ // a slave register is specified
+ slaveRegister = argv[2] + (argv[3] << 7);
+ data = argv[4] + (argv[5] << 7); // bytes to read
+ }
+ else {
+ // a slave register is NOT specified
+ slaveRegister = I2C_REGISTER_NOT_SPECIFIED;
+ data = argv[2] + (argv[3] << 7); // bytes to read
+ }
+ readAndReportData(slaveAddress, (int)slaveRegister, data, stopTX);
+ break;
+ case I2C_READ_CONTINUOUSLY:
+ if ((queryIndex + 1) >= I2C_MAX_QUERIES) {
+ // too many queries, just ignore
+ Firmata.sendString("too many queries");
+ break;
+ }
+ if (argc == 6) {
+ // a slave register is specified
+ slaveRegister = argv[2] + (argv[3] << 7);
+ data = argv[4] + (argv[5] << 7); // bytes to read
+ }
+ else {
+ // a slave register is NOT specified
+ slaveRegister = (int)I2C_REGISTER_NOT_SPECIFIED;
+ data = argv[2] + (argv[3] << 7); // bytes to read
+ }
+ queryIndex++;
+ query[queryIndex].addr = slaveAddress;
+ query[queryIndex].reg = slaveRegister;
+ query[queryIndex].bytes = data;
+ query[queryIndex].stopTX = stopTX;
+ break;
+ case I2C_STOP_READING:
+ byte queryIndexToSkip;
+ // if read continuous mode is enabled for only 1 i2c device, disable
+ // read continuous reporting for that device
+ if (queryIndex <= 0) {
+ queryIndex = -1;
+ } else {
+ queryIndexToSkip = 0;
+ // if read continuous mode is enabled for multiple devices,
+ // determine which device to stop reading and remove it's data from
+ // the array, shifiting other array data to fill the space
+ for (byte i = 0; i < queryIndex + 1; i++) {
+ if (query[i].addr == slaveAddress) {
+ queryIndexToSkip = i;
+ break;
+ }
+ }
+
+ for (byte i = queryIndexToSkip; i < queryIndex + 1; i++) {
+ if (i < I2C_MAX_QUERIES) {
+ query[i].addr = query[i + 1].addr;
+ query[i].reg = query[i + 1].reg;
+ query[i].bytes = query[i + 1].bytes;
+ query[i].stopTX = query[i + 1].stopTX;
+ }
+ }
+ queryIndex--;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case I2C_CONFIG:
+ delayTime = (argv[0] + (argv[1] << 7));
+
+ if (argc > 1 && delayTime > 0) {
+ i2cReadDelayTime = delayTime;
+ }
+
+ if (!isI2CEnabled) {
+ enableI2CPins();
+ }
+
+ break;
+ case SERVO_CONFIG:
+ if (argc > 4) {
+ // these vars are here for clarity, they'll optimized away by the compiler
+ byte pin = argv[0];
+ int minPulse = argv[1] + (argv[2] << 7);
+ int maxPulse = argv[3] + (argv[4] << 7);
+
+ if (IS_PIN_DIGITAL(pin)) {
+ if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) {
+ detachServo(pin);
+ }
+ attachServo(pin, minPulse, maxPulse);
+ setPinModeCallback(pin, PIN_MODE_SERVO);
+ }
+ }
+ break;
+ case SAMPLING_INTERVAL:
+ if (argc > 1) {
+ samplingInterval = argv[0] + (argv[1] << 7);
+ if (samplingInterval < MINIMUM_SAMPLING_INTERVAL) {
+ samplingInterval = MINIMUM_SAMPLING_INTERVAL;
+ }
+ } else {
+ //Firmata.sendString("Not enough data");
+ }
+ break;
+ case EXTENDED_ANALOG:
+ if (argc > 1) {
+ int val = argv[1];
+ if (argc > 2) val |= (argv[2] << 7);
+ if (argc > 3) val |= (argv[3] << 14);
+ analogWriteCallback(argv[0], val);
+ }
+ break;
+ case CAPABILITY_QUERY:
+ Firmata.write(START_SYSEX);
+ Firmata.write(CAPABILITY_RESPONSE);
+ for (byte pin = 0; pin < TOTAL_PINS; pin++) {
+ if (IS_PIN_DIGITAL(pin)) {
+ Firmata.write((byte)INPUT);
+ Firmata.write(1);
+ Firmata.write((byte)PIN_MODE_PULLUP);
+ Firmata.write(1);
+ Firmata.write((byte)OUTPUT);
+ Firmata.write(1);
+ }
+ if (IS_PIN_ANALOG(pin)) {
+ Firmata.write(PIN_MODE_ANALOG);
+ Firmata.write(10); // 10 = 10-bit resolution
+ }
+ if (IS_PIN_PWM(pin)) {
+ Firmata.write(PIN_MODE_PWM);
+ Firmata.write(DEFAULT_PWM_RESOLUTION);
+ }
+ if (IS_PIN_DIGITAL(pin)) {
+ Firmata.write(PIN_MODE_SERVO);
+ Firmata.write(14);
+ }
+ if (IS_PIN_I2C(pin)) {
+ Firmata.write(PIN_MODE_I2C);
+ Firmata.write(1); // TODO: could assign a number to map to SCL or SDA
+ }
+ Firmata.write(127);
+ }
+ Firmata.write(END_SYSEX);
+ break;
+ case PIN_STATE_QUERY:
+ if (argc > 0) {
+ byte pin = argv[0];
+ Firmata.write(START_SYSEX);
+ Firmata.write(PIN_STATE_RESPONSE);
+ Firmata.write(pin);
+ if (pin < TOTAL_PINS) {
+ Firmata.write(Firmata.getPinMode(pin));
+ Firmata.write((byte)Firmata.getPinState(pin) & 0x7F);
+ if (Firmata.getPinState(pin) & 0xFF80) Firmata.write((byte)(Firmata.getPinState(pin) >> 7) & 0x7F);
+ if (Firmata.getPinState(pin) & 0xC000) Firmata.write((byte)(Firmata.getPinState(pin) >> 14) & 0x7F);
+ }
+ Firmata.write(END_SYSEX);
+ }
+ break;
+ case ANALOG_MAPPING_QUERY:
+ Firmata.write(START_SYSEX);
+ Firmata.write(ANALOG_MAPPING_RESPONSE);
+ for (byte pin = 0; pin < TOTAL_PINS; pin++) {
+ Firmata.write(IS_PIN_ANALOG(pin) ? PIN_TO_ANALOG(pin) : 127);
+ }
+ Firmata.write(END_SYSEX);
+ break;
+ }
+}
+
+/*==============================================================================
+ * SETUP()
+ *============================================================================*/
+
+void systemResetCallback()
+{
+ isResetting = true;
+ // initialize a defalt state
+ // TODO: option to load config from EEPROM instead of default
+ if (isI2CEnabled) {
+ disableI2CPins();
+ }
+
+ for (byte i = 0; i < TOTAL_PORTS; i++) {
+ reportPINs[i] = false; // by default, reporting off
+ portConfigInputs[i] = 0; // until activated
+ previousPINs[i] = 0;
+ }
+
+ for (byte i = 0; i < TOTAL_PINS; i++) {
+ // pins with analog capability default to analog input
+ // otherwise, pins default to digital output
+ if (IS_PIN_ANALOG(i)) {
+ // turns off pullup, configures everything
+ setPinModeCallback(i, PIN_MODE_ANALOG);
+ } else if (IS_PIN_DIGITAL(i)) {
+ // sets the output to 0, configures portConfigInputs
+ setPinModeCallback(i, OUTPUT);
+ }
+
+ servoPinMap[i] = 255;
+ }
+ // by default, do not report any analog inputs
+ analogInputsToReport = 0;
+
+ detachedServoCount = 0;
+ servoCount = 0;
+
+ /* send digital inputs to set the initial state on the host computer,
+ * since once in the loop(), this firmware will only send on change */
+ /*
+ TODO: this can never execute, since no pins default to digital input
+ but it will be needed when/if we support EEPROM stored config
+ for (byte i=0; i < TOTAL_PORTS; i++) {
+ outputPort(i, readPort(i, portConfigInputs[i]), true);
+ }
+ */
+ isResetting = false;
+}
+
+void setup()
+{
+ Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
+
+ Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
+ Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
+ Firmata.attach(REPORT_ANALOG, reportAnalogCallback);
+ Firmata.attach(REPORT_DIGITAL, reportDigitalCallback);
+ Firmata.attach(SET_PIN_MODE, setPinModeCallback);
+ Firmata.attach(SET_DIGITAL_PIN_VALUE, setPinValueCallback);
+ Firmata.attach(START_SYSEX, sysexCallback);
+ Firmata.attach(SYSTEM_RESET, systemResetCallback);
+
+ /* For chipKIT Pi board, we need to use Serial1. All others just use Serial. */
+#if defined(_BOARD_CHIPKIT_PI_)
+ Serial1.begin(57600);
+ Firmata.begin(Serial1);
+#else
+ Firmata.begin(57600);
+#endif
+ systemResetCallback(); // reset to default config
+}
+
+/*==============================================================================
+ * LOOP()
+ *============================================================================*/
+void loop()
+{
+ byte pin, analogPin;
+
+ /* DIGITALREAD - as fast as possible, check for changes and output them to the
+ * FTDI buffer using Serial.print() */
+ checkDigitalInputs();
+
+ /* STREAMREAD - processing incoming messagse as soon as possible, while still
+ * checking digital inputs. */
+ while (Firmata.available())
+ Firmata.processInput();
+
+ // TODO - ensure that Stream buffer doesn't go over 60 bytes
+
+ currentMillis = millis();
+ if (currentMillis - previousMillis > samplingInterval) {
+ previousMillis += samplingInterval;
+ /* ANALOGREAD - do all analogReads() at the configured sampling interval */
+ for (pin = 0; pin < TOTAL_PINS; pin++) {
+ if (IS_PIN_ANALOG(pin) && Firmata.getPinMode(pin) == PIN_MODE_ANALOG) {
+ analogPin = PIN_TO_ANALOG(pin);
+ if (analogInputsToReport & (1 << analogPin)) {
+ Firmata.sendAnalog(analogPin, analogRead(analogPin));
+ }
+ }
+ }
+ // report i2c data for all device with read continuous mode enabled
+ if (queryIndex > -1) {
+ for (byte i = 0; i < queryIndex + 1; i++) {
+ readAndReportData(query[i].addr, query[i].reg, query[i].bytes, query[i].stopTX);
+ }
+ }
+ }
+}
--- /dev/null
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+\f
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
--- /dev/null
+/*
+ Firmata is a generic protocol for communicating with microcontrollers
+ from software on a host computer. It is intended to work with
+ any host computer software package.
+
+ To download a host software package, please click on the following link
+ to open the list of Firmata client libraries in your default browser.
+
+ https://github.com/firmata/arduino#firmata-client-libraries
+
+ Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.
+ Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved.
+ Copyright (C) 2009 Shigeru Kobayashi. All rights reserved.
+ Copyright (C) 2009-2017 Jeff Hoefs. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+
+ Last updated August 17th, 2017
+*/
+
+/*
+ README
+
+ StandardFirmataEthernet is a TCP client/server implementation. You will need a Firmata client library
+ with a network transport that can act as a TCP server or client in order to establish a connection between
+ StandardFirmataEthernet and the Firmata client application.
+
+ To use StandardFirmataEthernet you will need to have one of the following
+ boards or shields:
+
+ - Arduino Ethernet shield (or clone)
+ - Arduino Ethernet board (or clone)
+ - Arduino Yun
+
+ Follow the instructions in the ethernetConfig.h file (ethernetConfig.h tab in Arduino IDE) to
+ configure your particular hardware.
+
+ NOTE: If you are using an Arduino Ethernet shield you cannot use the following pins on
+ the following boards. Firmata will ignore any requests to use these pins:
+
+ - Arduino Uno or other ATMega328 boards: (D4, D10, D11, D12, D13)
+ - Arduino Mega: (D4, D10, D50, D51, D52, D53)
+ - Arduino Leonardo: (D4, D10)
+ - Arduino Due: (D4, D10)
+ - Arduino Zero: (D4, D10)
+
+ If you are using an ArduinoEthernet board, the following pins cannot be used (same as Uno):
+ - D4, D10, D11, D12, D13
+*/
+
+#include <Servo.h>
+#include <Wire.h>
+#include <Firmata.h>
+
+/*
+ * Uncomment the #define SERIAL_DEBUG line below to receive serial output messages relating to your
+ * connection that may help in the event of connection issues. If defined, some boards may not begin
+ * executing this sketch until the Serial console is opened.
+ */
+//#define SERIAL_DEBUG
+#include "utility/firmataDebug.h"
+
+// follow the instructions in ethernetConfig.h to configure your particular hardware
+#include "ethernetConfig.h"
+#include "utility/EthernetClientStream.h"
+#include "utility/EthernetServerStream.h"
+
+/*
+ * Uncomment the following include to enable interfacing with Serial devices via hardware or
+ * software serial.
+ *
+ * DO NOT uncomment if you are running StandardFirmataEthernet on an Arduino Leonardo,
+ * Arduino Micro or other ATMega32u4-based board or you will not have enough Flash and RAM
+ * remaining to reliably run Firmata. Arduino Yun is okay because it doesn't import the Ethernet
+ * libraries.
+ */
+// In order to use software serial, you will need to compile this sketch with
+// Arduino IDE v1.6.6 or higher. Hardware serial should work back to Arduino 1.0.
+//#include "utility/SerialFirmata.h"
+
+#define I2C_WRITE B00000000
+#define I2C_READ B00001000
+#define I2C_READ_CONTINUOUSLY B00010000
+#define I2C_STOP_READING B00011000
+#define I2C_READ_WRITE_MODE_MASK B00011000
+#define I2C_10BIT_ADDRESS_MODE_MASK B00100000
+#define I2C_END_TX_MASK B01000000
+#define I2C_STOP_TX 1
+#define I2C_RESTART_TX 0
+#define I2C_MAX_QUERIES 8
+#define I2C_REGISTER_NOT_SPECIFIED -1
+
+// the minimum interval for sampling analog input
+#define MINIMUM_SAMPLING_INTERVAL 1
+
+/*==============================================================================
+ * GLOBAL VARIABLES
+ *============================================================================*/
+
+#if defined remote_ip && !defined remote_host
+#ifdef local_ip
+EthernetClientStream stream(client, local_ip, remote_ip, NULL, network_port);
+#else
+EthernetClientStream stream(client, IPAddress(0, 0, 0, 0), remote_ip, NULL, network_port);
+#endif
+#endif
+
+#if !defined remote_ip && defined remote_host
+#ifdef local_ip
+EthernetClientStream stream(client, local_ip, IPAddress(0, 0, 0, 0), remote_host, network_port );
+#else
+EthernetClientStream stream(client, IPAddress(0, 0, 0, 0), IPAddress(0, 0, 0, 0), remote_host, network_port);
+#endif
+#endif
+
+#if !defined remote_ip && !defined remote_host
+#ifdef local_ip
+EthernetServerStream stream(local_ip, network_port);
+#else
+EthernetServerStream stream(IPAddress(0, 0, 0, 0), network_port);
+#endif
+#endif
+
+#ifdef FIRMATA_SERIAL_FEATURE
+SerialFirmata serialFeature;
+#endif
+
+/* analog inputs */
+int analogInputsToReport = 0; // bitwise array to store pin reporting
+
+/* digital input ports */
+byte reportPINs[TOTAL_PORTS]; // 1 = report this port, 0 = silence
+byte previousPINs[TOTAL_PORTS]; // previous 8 bits sent
+
+/* pins configuration */
+byte portConfigInputs[TOTAL_PORTS]; // each bit: 1 = pin in INPUT, 0 = anything else
+
+/* timer variables */
+unsigned long currentMillis; // store the current value from millis()
+unsigned long previousMillis; // for comparison with currentMillis
+unsigned int samplingInterval = 19; // how often to sample analog inputs (in ms)
+
+/* i2c data */
+struct i2c_device_info {
+ byte addr;
+ int reg;
+ byte bytes;
+ byte stopTX;
+};
+
+/* for i2c read continuous mode */
+i2c_device_info query[I2C_MAX_QUERIES];
+
+byte i2cRxData[64];
+boolean isI2CEnabled = false;
+signed char queryIndex = -1;
+// default delay time between i2c read request and Wire.requestFrom()
+unsigned int i2cReadDelayTime = 0;
+
+Servo servos[MAX_SERVOS];
+byte servoPinMap[TOTAL_PINS];
+byte detachedServos[MAX_SERVOS];
+byte detachedServoCount = 0;
+byte servoCount = 0;
+
+boolean isResetting = false;
+
+// Forward declare a few functions to avoid compiler errors with older versions
+// of the Arduino IDE.
+void setPinModeCallback(byte, int);
+void reportAnalogCallback(byte analogPin, int value);
+void sysexCallback(byte, byte, byte*);
+
+/* utility functions */
+void wireWrite(byte data)
+{
+#if ARDUINO >= 100
+ Wire.write((byte)data);
+#else
+ Wire.send(data);
+#endif
+}
+
+byte wireRead(void)
+{
+#if ARDUINO >= 100
+ return Wire.read();
+#else
+ return Wire.receive();
+#endif
+}
+
+/*==============================================================================
+ * FUNCTIONS
+ *============================================================================*/
+
+void attachServo(byte pin, int minPulse, int maxPulse)
+{
+ if (servoCount < MAX_SERVOS) {
+ // reuse indexes of detached servos until all have been reallocated
+ if (detachedServoCount > 0) {
+ servoPinMap[pin] = detachedServos[detachedServoCount - 1];
+ if (detachedServoCount > 0) detachedServoCount--;
+ } else {
+ servoPinMap[pin] = servoCount;
+ servoCount++;
+ }
+ if (minPulse > 0 && maxPulse > 0) {
+ servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin), minPulse, maxPulse);
+ } else {
+ servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin));
+ }
+ } else {
+ Firmata.sendString("Max servos attached");
+ }
+}
+
+void detachServo(byte pin)
+{
+ servos[servoPinMap[pin]].detach();
+ // if we're detaching the last servo, decrement the count
+ // otherwise store the index of the detached servo
+ if (servoPinMap[pin] == servoCount && servoCount > 0) {
+ servoCount--;
+ } else if (servoCount > 0) {
+ // keep track of detached servos because we want to reuse their indexes
+ // before incrementing the count of attached servos
+ detachedServoCount++;
+ detachedServos[detachedServoCount - 1] = servoPinMap[pin];
+ }
+
+ servoPinMap[pin] = 255;
+}
+
+void enableI2CPins()
+{
+ byte i;
+ // is there a faster way to do this? would probaby require importing
+ // Arduino.h to get SCL and SDA pins
+ for (i = 0; i < TOTAL_PINS; i++) {
+ if (IS_PIN_I2C(i)) {
+ // mark pins as i2c so they are ignore in non i2c data requests
+ setPinModeCallback(i, PIN_MODE_I2C);
+ }
+ }
+
+ isI2CEnabled = true;
+
+ Wire.begin();
+}
+
+/* disable the i2c pins so they can be used for other functions */
+void disableI2CPins() {
+ isI2CEnabled = false;
+ // disable read continuous mode for all devices
+ queryIndex = -1;
+}
+
+void readAndReportData(byte address, int theRegister, byte numBytes, byte stopTX) {
+ // allow I2C requests that don't require a register read
+ // for example, some devices using an interrupt pin to signify new data available
+ // do not always require the register read so upon interrupt you call Wire.requestFrom()
+ if (theRegister != I2C_REGISTER_NOT_SPECIFIED) {
+ Wire.beginTransmission(address);
+ wireWrite((byte)theRegister);
+ Wire.endTransmission(stopTX); // default = true
+ // do not set a value of 0
+ if (i2cReadDelayTime > 0) {
+ // delay is necessary for some devices such as WiiNunchuck
+ delayMicroseconds(i2cReadDelayTime);
+ }
+ } else {
+ theRegister = 0; // fill the register with a dummy value
+ }
+
+ Wire.requestFrom(address, numBytes); // all bytes are returned in requestFrom
+
+ // check to be sure correct number of bytes were returned by slave
+ if (numBytes < Wire.available()) {
+ Firmata.sendString("I2C: Too many bytes received");
+ } else if (numBytes > Wire.available()) {
+ Firmata.sendString("I2C: Too few bytes received");
+ }
+
+ i2cRxData[0] = address;
+ i2cRxData[1] = theRegister;
+
+ for (int i = 0; i < numBytes && Wire.available(); i++) {
+ i2cRxData[2 + i] = wireRead();
+ }
+
+ // send slave address, register and received bytes
+ Firmata.sendSysex(SYSEX_I2C_REPLY, numBytes + 2, i2cRxData);
+}
+
+void outputPort(byte portNumber, byte portValue, byte forceSend)
+{
+ // pins not configured as INPUT are cleared to zeros
+ portValue = portValue & portConfigInputs[portNumber];
+ // only send if the value is different than previously sent
+ if (forceSend || previousPINs[portNumber] != portValue) {
+ Firmata.sendDigitalPort(portNumber, portValue);
+ previousPINs[portNumber] = portValue;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * check all the active digital inputs for change of state, then add any events
+ * to the Stream output queue using Stream.write() */
+void checkDigitalInputs(void)
+{
+ /* Using non-looping code allows constants to be given to readPort().
+ * The compiler will apply substantial optimizations if the inputs
+ * to readPort() are compile-time constants. */
+ if (TOTAL_PORTS > 0 && reportPINs[0]) outputPort(0, readPort(0, portConfigInputs[0]), false);
+ if (TOTAL_PORTS > 1 && reportPINs[1]) outputPort(1, readPort(1, portConfigInputs[1]), false);
+ if (TOTAL_PORTS > 2 && reportPINs[2]) outputPort(2, readPort(2, portConfigInputs[2]), false);
+ if (TOTAL_PORTS > 3 && reportPINs[3]) outputPort(3, readPort(3, portConfigInputs[3]), false);
+ if (TOTAL_PORTS > 4 && reportPINs[4]) outputPort(4, readPort(4, portConfigInputs[4]), false);
+ if (TOTAL_PORTS > 5 && reportPINs[5]) outputPort(5, readPort(5, portConfigInputs[5]), false);
+ if (TOTAL_PORTS > 6 && reportPINs[6]) outputPort(6, readPort(6, portConfigInputs[6]), false);
+ if (TOTAL_PORTS > 7 && reportPINs[7]) outputPort(7, readPort(7, portConfigInputs[7]), false);
+ if (TOTAL_PORTS > 8 && reportPINs[8]) outputPort(8, readPort(8, portConfigInputs[8]), false);
+ if (TOTAL_PORTS > 9 && reportPINs[9]) outputPort(9, readPort(9, portConfigInputs[9]), false);
+ if (TOTAL_PORTS > 10 && reportPINs[10]) outputPort(10, readPort(10, portConfigInputs[10]), false);
+ if (TOTAL_PORTS > 11 && reportPINs[11]) outputPort(11, readPort(11, portConfigInputs[11]), false);
+ if (TOTAL_PORTS > 12 && reportPINs[12]) outputPort(12, readPort(12, portConfigInputs[12]), false);
+ if (TOTAL_PORTS > 13 && reportPINs[13]) outputPort(13, readPort(13, portConfigInputs[13]), false);
+ if (TOTAL_PORTS > 14 && reportPINs[14]) outputPort(14, readPort(14, portConfigInputs[14]), false);
+ if (TOTAL_PORTS > 15 && reportPINs[15]) outputPort(15, readPort(15, portConfigInputs[15]), false);
+}
+
+// -----------------------------------------------------------------------------
+/* sets the pin mode to the correct state and sets the relevant bits in the
+ * two bit-arrays that track Digital I/O and PWM status
+ */
+void setPinModeCallback(byte pin, int mode)
+{
+ if (Firmata.getPinMode(pin) == PIN_MODE_IGNORE)
+ return;
+
+ if (Firmata.getPinMode(pin) == PIN_MODE_I2C && isI2CEnabled && mode != PIN_MODE_I2C) {
+ // disable i2c so pins can be used for other functions
+ // the following if statements should reconfigure the pins properly
+ disableI2CPins();
+ }
+ if (IS_PIN_DIGITAL(pin) && mode != PIN_MODE_SERVO) {
+ if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) {
+ detachServo(pin);
+ }
+ }
+ if (IS_PIN_ANALOG(pin)) {
+ // turn on/off reporting
+ reportAnalogCallback(PIN_TO_ANALOG(pin), mode == PIN_MODE_ANALOG ? 1 : 0);
+ }
+ if (IS_PIN_DIGITAL(pin)) {
+ if (mode == INPUT || mode == PIN_MODE_PULLUP) {
+ portConfigInputs[pin / 8] |= (1 << (pin & 7));
+ } else {
+ portConfigInputs[pin / 8] &= ~(1 << (pin & 7));
+ }
+ }
+ Firmata.setPinState(pin, 0);
+ switch (mode) {
+ case PIN_MODE_ANALOG:
+ if (IS_PIN_ANALOG(pin)) {
+ if (IS_PIN_DIGITAL(pin)) {
+ pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
+#if ARDUINO <= 100
+ // deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6
+ digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
+#endif
+ }
+ Firmata.setPinMode(pin, PIN_MODE_ANALOG);
+ }
+ break;
+ case INPUT:
+ if (IS_PIN_DIGITAL(pin)) {
+ pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
+#if ARDUINO <= 100
+ // deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6
+ digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
+#endif
+ Firmata.setPinMode(pin, INPUT);
+ }
+ break;
+ case PIN_MODE_PULLUP:
+ if (IS_PIN_DIGITAL(pin)) {
+ pinMode(PIN_TO_DIGITAL(pin), INPUT_PULLUP);
+ Firmata.setPinMode(pin, PIN_MODE_PULLUP);
+ Firmata.setPinState(pin, 1);
+ }
+ break;
+ case OUTPUT:
+ if (IS_PIN_DIGITAL(pin)) {
+ if (Firmata.getPinMode(pin) == PIN_MODE_PWM) {
+ // Disable PWM if pin mode was previously set to PWM.
+ digitalWrite(PIN_TO_DIGITAL(pin), LOW);
+ }
+ pinMode(PIN_TO_DIGITAL(pin), OUTPUT);
+ Firmata.setPinMode(pin, OUTPUT);
+ }
+ break;
+ case PIN_MODE_PWM:
+ if (IS_PIN_PWM(pin)) {
+ pinMode(PIN_TO_PWM(pin), OUTPUT);
+ analogWrite(PIN_TO_PWM(pin), 0);
+ Firmata.setPinMode(pin, PIN_MODE_PWM);
+ }
+ break;
+ case PIN_MODE_SERVO:
+ if (IS_PIN_DIGITAL(pin)) {
+ Firmata.setPinMode(pin, PIN_MODE_SERVO);
+ if (servoPinMap[pin] == 255 || !servos[servoPinMap[pin]].attached()) {
+ // pass -1 for min and max pulse values to use default values set
+ // by Servo library
+ attachServo(pin, -1, -1);
+ }
+ }
+ break;
+ case PIN_MODE_I2C:
+ if (IS_PIN_I2C(pin)) {
+ // mark the pin as i2c
+ // the user must call I2C_CONFIG to enable I2C for a device
+ Firmata.setPinMode(pin, PIN_MODE_I2C);
+ }
+ break;
+ case PIN_MODE_SERIAL:
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.handlePinMode(pin, PIN_MODE_SERIAL);
+#endif
+ break;
+ default:
+ Firmata.sendString("Unknown pin mode"); // TODO: put error msgs in EEPROM
+ }
+ // TODO: save status to EEPROM here, if changed
+}
+
+/*
+ * Sets the value of an individual pin. Useful if you want to set a pin value but
+ * are not tracking the digital port state.
+ * Can only be used on pins configured as OUTPUT.
+ * Cannot be used to enable pull-ups on Digital INPUT pins.
+ */
+void setPinValueCallback(byte pin, int value)
+{
+ if (pin < TOTAL_PINS && IS_PIN_DIGITAL(pin)) {
+ if (Firmata.getPinMode(pin) == OUTPUT) {
+ Firmata.setPinState(pin, value);
+ digitalWrite(PIN_TO_DIGITAL(pin), value);
+ }
+ }
+}
+
+void analogWriteCallback(byte pin, int value)
+{
+ if (pin < TOTAL_PINS) {
+ switch (Firmata.getPinMode(pin)) {
+ case PIN_MODE_SERVO:
+ if (IS_PIN_DIGITAL(pin))
+ servos[servoPinMap[pin]].write(value);
+ Firmata.setPinState(pin, value);
+ break;
+ case PIN_MODE_PWM:
+ if (IS_PIN_PWM(pin))
+ analogWrite(PIN_TO_PWM(pin), value);
+ Firmata.setPinState(pin, value);
+ break;
+ }
+ }
+}
+
+void digitalWriteCallback(byte port, int value)
+{
+ byte pin, lastPin, pinValue, mask = 1, pinWriteMask = 0;
+
+ if (port < TOTAL_PORTS) {
+ // create a mask of the pins on this port that are writable.
+ lastPin = port * 8 + 8;
+ if (lastPin > TOTAL_PINS) lastPin = TOTAL_PINS;
+ for (pin = port * 8; pin < lastPin; pin++) {
+ // do not disturb non-digital pins (eg, Rx & Tx)
+ if (IS_PIN_DIGITAL(pin)) {
+ // do not touch pins in PWM, ANALOG, SERVO or other modes
+ if (Firmata.getPinMode(pin) == OUTPUT || Firmata.getPinMode(pin) == INPUT) {
+ pinValue = ((byte)value & mask) ? 1 : 0;
+ if (Firmata.getPinMode(pin) == OUTPUT) {
+ pinWriteMask |= mask;
+ } else if (Firmata.getPinMode(pin) == INPUT && pinValue == 1 && Firmata.getPinState(pin) != 1) {
+ // only handle INPUT here for backwards compatibility
+#if ARDUINO > 100
+ pinMode(pin, INPUT_PULLUP);
+#else
+ // only write to the INPUT pin to enable pullups if Arduino v1.0.0 or earlier
+ pinWriteMask |= mask;
+#endif
+ }
+ Firmata.setPinState(pin, pinValue);
+ }
+ }
+ mask = mask << 1;
+ }
+ writePort(port, (byte)value, pinWriteMask);
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+/* sets bits in a bit array (int) to toggle the reporting of the analogIns
+ */
+//void FirmataClass::setAnalogPinReporting(byte pin, byte state) {
+//}
+void reportAnalogCallback(byte analogPin, int value)
+{
+ if (analogPin < TOTAL_ANALOG_PINS) {
+ if (value == 0) {
+ analogInputsToReport = analogInputsToReport & ~ (1 << analogPin);
+ } else {
+ analogInputsToReport = analogInputsToReport | (1 << analogPin);
+ // prevent during system reset or all analog pin values will be reported
+ // which may report noise for unconnected analog pins
+ if (!isResetting) {
+ // Send pin value immediately. This is helpful when connected via
+ // ethernet, wi-fi or bluetooth so pin states can be known upon
+ // reconnecting.
+ Firmata.sendAnalog(analogPin, analogRead(analogPin));
+ }
+ }
+ }
+ // TODO: save status to EEPROM here, if changed
+}
+
+void reportDigitalCallback(byte port, int value)
+{
+ if (port < TOTAL_PORTS) {
+ reportPINs[port] = (byte)value;
+ // Send port value immediately. This is helpful when connected via
+ // ethernet, wi-fi or bluetooth so pin states can be known upon
+ // reconnecting.
+ if (value) outputPort(port, readPort(port, portConfigInputs[port]), true);
+ }
+ // do not disable analog reporting on these 8 pins, to allow some
+ // pins used for digital, others analog. Instead, allow both types
+ // of reporting to be enabled, but check if the pin is configured
+ // as analog when sampling the analog inputs. Likewise, while
+ // scanning digital pins, portConfigInputs will mask off values from any
+ // pins configured as analog
+}
+
+/*==============================================================================
+ * SYSEX-BASED commands
+ *============================================================================*/
+
+void sysexCallback(byte command, byte argc, byte *argv)
+{
+ byte mode;
+ byte stopTX;
+ byte slaveAddress;
+ byte data;
+ int slaveRegister;
+ unsigned int delayTime;
+
+ switch (command) {
+ case I2C_REQUEST:
+ mode = argv[1] & I2C_READ_WRITE_MODE_MASK;
+ if (argv[1] & I2C_10BIT_ADDRESS_MODE_MASK) {
+ Firmata.sendString("10-bit addressing not supported");
+ return;
+ }
+ else {
+ slaveAddress = argv[0];
+ }
+
+ // need to invert the logic here since 0 will be default for client
+ // libraries that have not updated to add support for restart tx
+ if (argv[1] & I2C_END_TX_MASK) {
+ stopTX = I2C_RESTART_TX;
+ }
+ else {
+ stopTX = I2C_STOP_TX; // default
+ }
+
+ switch (mode) {
+ case I2C_WRITE:
+ Wire.beginTransmission(slaveAddress);
+ for (byte i = 2; i < argc; i += 2) {
+ data = argv[i] + (argv[i + 1] << 7);
+ wireWrite(data);
+ }
+ Wire.endTransmission();
+ delayMicroseconds(70);
+ break;
+ case I2C_READ:
+ if (argc == 6) {
+ // a slave register is specified
+ slaveRegister = argv[2] + (argv[3] << 7);
+ data = argv[4] + (argv[5] << 7); // bytes to read
+ }
+ else {
+ // a slave register is NOT specified
+ slaveRegister = I2C_REGISTER_NOT_SPECIFIED;
+ data = argv[2] + (argv[3] << 7); // bytes to read
+ }
+ readAndReportData(slaveAddress, (int)slaveRegister, data, stopTX);
+ break;
+ case I2C_READ_CONTINUOUSLY:
+ if ((queryIndex + 1) >= I2C_MAX_QUERIES) {
+ // too many queries, just ignore
+ Firmata.sendString("too many queries");
+ break;
+ }
+ if (argc == 6) {
+ // a slave register is specified
+ slaveRegister = argv[2] + (argv[3] << 7);
+ data = argv[4] + (argv[5] << 7); // bytes to read
+ }
+ else {
+ // a slave register is NOT specified
+ slaveRegister = (int)I2C_REGISTER_NOT_SPECIFIED;
+ data = argv[2] + (argv[3] << 7); // bytes to read
+ }
+ queryIndex++;
+ query[queryIndex].addr = slaveAddress;
+ query[queryIndex].reg = slaveRegister;
+ query[queryIndex].bytes = data;
+ query[queryIndex].stopTX = stopTX;
+ break;
+ case I2C_STOP_READING:
+ byte queryIndexToSkip;
+ // if read continuous mode is enabled for only 1 i2c device, disable
+ // read continuous reporting for that device
+ if (queryIndex <= 0) {
+ queryIndex = -1;
+ } else {
+ queryIndexToSkip = 0;
+ // if read continuous mode is enabled for multiple devices,
+ // determine which device to stop reading and remove it's data from
+ // the array, shifiting other array data to fill the space
+ for (byte i = 0; i < queryIndex + 1; i++) {
+ if (query[i].addr == slaveAddress) {
+ queryIndexToSkip = i;
+ break;
+ }
+ }
+
+ for (byte i = queryIndexToSkip; i < queryIndex + 1; i++) {
+ if (i < I2C_MAX_QUERIES) {
+ query[i].addr = query[i + 1].addr;
+ query[i].reg = query[i + 1].reg;
+ query[i].bytes = query[i + 1].bytes;
+ query[i].stopTX = query[i + 1].stopTX;
+ }
+ }
+ queryIndex--;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case I2C_CONFIG:
+ delayTime = (argv[0] + (argv[1] << 7));
+
+ if (argc > 1 && delayTime > 0) {
+ i2cReadDelayTime = delayTime;
+ }
+
+ if (!isI2CEnabled) {
+ enableI2CPins();
+ }
+
+ break;
+ case SERVO_CONFIG:
+ if (argc > 4) {
+ // these vars are here for clarity, they'll optimized away by the compiler
+ byte pin = argv[0];
+ int minPulse = argv[1] + (argv[2] << 7);
+ int maxPulse = argv[3] + (argv[4] << 7);
+
+ if (IS_PIN_DIGITAL(pin)) {
+ if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) {
+ detachServo(pin);
+ }
+ attachServo(pin, minPulse, maxPulse);
+ setPinModeCallback(pin, PIN_MODE_SERVO);
+ }
+ }
+ break;
+ case SAMPLING_INTERVAL:
+ if (argc > 1) {
+ samplingInterval = argv[0] + (argv[1] << 7);
+ if (samplingInterval < MINIMUM_SAMPLING_INTERVAL) {
+ samplingInterval = MINIMUM_SAMPLING_INTERVAL;
+ }
+ } else {
+ //Firmata.sendString("Not enough data");
+ }
+ break;
+ case EXTENDED_ANALOG:
+ if (argc > 1) {
+ int val = argv[1];
+ if (argc > 2) val |= (argv[2] << 7);
+ if (argc > 3) val |= (argv[3] << 14);
+ analogWriteCallback(argv[0], val);
+ }
+ break;
+ case CAPABILITY_QUERY:
+ Firmata.write(START_SYSEX);
+ Firmata.write(CAPABILITY_RESPONSE);
+ for (byte pin = 0; pin < TOTAL_PINS; pin++) {
+ if (IS_PIN_DIGITAL(pin)) {
+ Firmata.write((byte)INPUT);
+ Firmata.write(1);
+ Firmata.write((byte)PIN_MODE_PULLUP);
+ Firmata.write(1);
+ Firmata.write((byte)OUTPUT);
+ Firmata.write(1);
+ }
+ if (IS_PIN_ANALOG(pin)) {
+ Firmata.write(PIN_MODE_ANALOG);
+ Firmata.write(10); // 10 = 10-bit resolution
+ }
+ if (IS_PIN_PWM(pin)) {
+ Firmata.write(PIN_MODE_PWM);
+ Firmata.write(DEFAULT_PWM_RESOLUTION);
+ }
+ if (IS_PIN_DIGITAL(pin)) {
+ Firmata.write(PIN_MODE_SERVO);
+ Firmata.write(14);
+ }
+ if (IS_PIN_I2C(pin)) {
+ Firmata.write(PIN_MODE_I2C);
+ Firmata.write(1); // TODO: could assign a number to map to SCL or SDA
+ }
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.handleCapability(pin);
+#endif
+ Firmata.write(127);
+ }
+ Firmata.write(END_SYSEX);
+ break;
+ case PIN_STATE_QUERY:
+ if (argc > 0) {
+ byte pin = argv[0];
+ Firmata.write(START_SYSEX);
+ Firmata.write(PIN_STATE_RESPONSE);
+ Firmata.write(pin);
+ if (pin < TOTAL_PINS) {
+ Firmata.write(Firmata.getPinMode(pin));
+ Firmata.write((byte)Firmata.getPinState(pin) & 0x7F);
+ if (Firmata.getPinState(pin) & 0xFF80) Firmata.write((byte)(Firmata.getPinState(pin) >> 7) & 0x7F);
+ if (Firmata.getPinState(pin) & 0xC000) Firmata.write((byte)(Firmata.getPinState(pin) >> 14) & 0x7F);
+ }
+ Firmata.write(END_SYSEX);
+ }
+ break;
+ case ANALOG_MAPPING_QUERY:
+ Firmata.write(START_SYSEX);
+ Firmata.write(ANALOG_MAPPING_RESPONSE);
+ for (byte pin = 0; pin < TOTAL_PINS; pin++) {
+ Firmata.write(IS_PIN_ANALOG(pin) ? PIN_TO_ANALOG(pin) : 127);
+ }
+ Firmata.write(END_SYSEX);
+ break;
+
+ case SERIAL_MESSAGE:
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.handleSysex(command, argc, argv);
+#endif
+ break;
+ }
+}
+
+/*==============================================================================
+ * SETUP()
+ *============================================================================*/
+
+void systemResetCallback()
+{
+ isResetting = true;
+
+ // initialize a defalt state
+ // TODO: option to load config from EEPROM instead of default
+
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.reset();
+#endif
+
+ if (isI2CEnabled) {
+ disableI2CPins();
+ }
+
+ for (byte i = 0; i < TOTAL_PORTS; i++) {
+ reportPINs[i] = false; // by default, reporting off
+ portConfigInputs[i] = 0; // until activated
+ previousPINs[i] = 0;
+ }
+
+ for (byte i = 0; i < TOTAL_PINS; i++) {
+ // pins with analog capability default to analog input
+ // otherwise, pins default to digital output
+ if (IS_PIN_ANALOG(i)) {
+ // turns off pullup, configures everything
+ setPinModeCallback(i, PIN_MODE_ANALOG);
+ } else if (IS_PIN_DIGITAL(i)) {
+ // sets the output to 0, configures portConfigInputs
+ setPinModeCallback(i, OUTPUT);
+ }
+
+ servoPinMap[i] = 255;
+ }
+ // by default, do not report any analog inputs
+ analogInputsToReport = 0;
+
+ detachedServoCount = 0;
+ servoCount = 0;
+
+ /* send digital inputs to set the initial state on the host computer,
+ * since once in the loop(), this firmware will only send on change */
+ /*
+ TODO: this can never execute, since no pins default to digital input
+ but it will be needed when/if we support EEPROM stored config
+ for (byte i=0; i < TOTAL_PORTS; i++) {
+ outputPort(i, readPort(i, portConfigInputs[i]), true);
+ }
+ */
+ isResetting = false;
+}
+
+void printEthernetStatus()
+{
+ DEBUG_PRINT("Local IP Address: ");
+ IPAddress ip = Ethernet.localIP();
+ DEBUG_PRINTLN(ip);
+#ifdef remote_ip
+ DEBUG_PRINT("Connecting to server at: ");
+ DEBUG_PRINTLN(remote_ip);
+#endif
+}
+
+/*
+ * StandardFirmataEthernet communicates with Ethernet shields over SPI. Therefore all
+ * SPI pins must be set to IGNORE. Otherwise Firmata would break SPI communication.
+ * Additional pins may also need to be ignored depending on the particular board or
+ * shield in use.
+ */
+void ignorePins()
+{
+#ifdef IS_IGNORE_PIN
+ for (byte i = 0; i < TOTAL_PINS; i++) {
+ if (IS_IGNORE_PIN(i)) {
+ Firmata.setPinMode(i, PIN_MODE_IGNORE);
+ }
+ }
+#endif
+
+#ifdef WIZ5100_ETHERNET
+ // Arduino Ethernet and Arduino EthernetShield have SD SS wired to D4
+ pinMode(PIN_TO_DIGITAL(4), OUTPUT); // switch off SD card bypassing Firmata
+ digitalWrite(PIN_TO_DIGITAL(4), HIGH); // SS is active low;
+
+#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
+ pinMode(PIN_TO_DIGITAL(53), OUTPUT); // configure hardware SS as output on MEGA
+#endif
+
+#endif // WIZ5100_ETHERNET
+}
+
+void initTransport()
+{
+#ifdef YUN_ETHERNET
+ Bridge.begin();
+#else
+#ifdef local_ip
+ Ethernet.begin((uint8_t *)mac, local_ip); //start ethernet
+#else
+ DEBUG_PRINTLN("Local IP will be requested from DHCP...");
+ //start ethernet using dhcp
+ if (Ethernet.begin((uint8_t *)mac) == 0) {
+ DEBUG_PRINTLN("Failed to configure Ethernet using DHCP");
+ }
+#endif
+#endif
+ printEthernetStatus();
+}
+
+void initFirmata()
+{
+ Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
+ Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
+ Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
+ Firmata.attach(REPORT_ANALOG, reportAnalogCallback);
+ Firmata.attach(REPORT_DIGITAL, reportDigitalCallback);
+ Firmata.attach(SET_PIN_MODE, setPinModeCallback);
+ Firmata.attach(SET_DIGITAL_PIN_VALUE, setPinValueCallback);
+ Firmata.attach(START_SYSEX, sysexCallback);
+ Firmata.attach(SYSTEM_RESET, systemResetCallback);
+
+ ignorePins();
+
+ // start up Network Firmata:
+ Firmata.begin(stream);
+ systemResetCallback(); // Initialize default configuration
+}
+
+void setup()
+{
+ DEBUG_BEGIN(9600);
+
+ initTransport();
+
+ initFirmata();
+}
+
+/*==============================================================================
+ * LOOP()
+ *============================================================================*/
+void loop()
+{
+ byte pin, analogPin;
+
+ /* DIGITALREAD - as fast as possible, check for changes and output them to the
+ * Stream buffer using Stream.write() */
+ checkDigitalInputs();
+
+ /* STREAMREAD - processing incoming messagse as soon as possible, while still
+ * checking digital inputs. */
+ while (Firmata.available())
+ Firmata.processInput();
+
+ // TODO - ensure that Stream buffer doesn't go over 60 bytes
+
+ currentMillis = millis();
+ if (currentMillis - previousMillis > samplingInterval) {
+ previousMillis += samplingInterval;
+ /* ANALOGREAD - do all analogReads() at the configured sampling interval */
+ for (pin = 0; pin < TOTAL_PINS; pin++) {
+ if (IS_PIN_ANALOG(pin) && Firmata.getPinMode(pin) == PIN_MODE_ANALOG) {
+ analogPin = PIN_TO_ANALOG(pin);
+ if (analogInputsToReport & (1 << analogPin)) {
+ Firmata.sendAnalog(analogPin, analogRead(analogPin));
+ }
+ }
+ }
+ // report i2c data for all device with read continuous mode enabled
+ if (queryIndex > -1) {
+ for (byte i = 0; i < queryIndex + 1; i++) {
+ readAndReportData(query[i].addr, query[i].reg, query[i].bytes, query[i].stopTX);
+ }
+ }
+ }
+
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.update();
+#endif
+
+#if !defined local_ip && !defined YUN_ETHERNET
+ // only necessary when using DHCP, ensures local IP is updated appropriately if it changes
+ if (Ethernet.maintain()) {
+ stream.maintain(Ethernet.localIP());
+ }
+#endif
+
+}
--- /dev/null
+/*==============================================================================
+ * NETWORK CONFIGURATION
+ *
+ * You must configure your particular hardware. Follow the steps below.
+ *
+ * By default, StandardFirmataEthernet is configured as a TCP client.
+ * To configure as a TCP server, see STEP 2
+ *============================================================================*/
+
+// STEP 1 [REQUIRED]
+// Uncomment / comment the appropriate set of includes for your hardware (OPTION A or B)
+// Option A is enabled by default.
+
+/*
+ * OPTION A: Configure for Arduino Ethernet board or Arduino Ethernet shield (or clone)
+ *
+ * To configure StandardFirmataEthernet to use the original WIZ5100-based
+ * ethernet shield or Arduino Ethernet uncomment the WIZ5100_ETHERNET define below
+ */
+#define WIZ5100_ETHERNET
+
+#ifdef WIZ5100_ETHERNET
+#include <SPI.h>
+#include <Ethernet.h>
+EthernetClient client;
+#endif
+
+/*
+ * OPTION B: Configure for Arduin Yun
+ *
+ * The Ethernet port on the Arduino Yun board can be used with Firmata in this configuration.
+ *
+ * To execute StandardFirmataEthernet on Yun uncomment the YUN_ETHERNET define below and make
+ * sure the WIZ5100_ETHERNET define (above) is commented out.
+ *
+ * On Yun there's no need to configure local_ip and mac address as this is automatically
+ * configured on the linux-side of Yun.
+ *
+ * Note that it may take several seconds to establish a connection with the Yun.
+ */
+//#define YUN_ETHERNET
+
+#ifdef YUN_ETHERNET
+#include <Bridge.h>
+#include <YunClient.h>
+YunClient client;
+#endif
+
+// STEP 2 [REQUIRED for all boards and shields]
+// TCP Client configuration:
+// To configure your board as a TCP client, set the IP address of the server you want to connect to.
+// TCP Server configuration:
+// To configure your board as a TCP server, comment out the following line and also ensure that
+// remote_host is also commented out.
+#define remote_ip IPAddress(10, 0, 0, 3)
+// *** REMOTE HOST IS NOT YET WORKING ***
+// replace with hostname of server you want to connect to, comment out if using 'remote_ip'
+// #define remote_host "server.local"
+
+// STEP 3 [REQUIRED]
+// Replace with the port that your client or server is listening on.
+#define network_port 3030
+
+// STEP 4 [REQUIRED unless using DHCP]
+// Replace with your board or ethernet shield's IP address
+// Comment out if you want to use DHCP
+#define local_ip IPAddress(10, 0, 0, 15)
+
+// STEP 5 [REQUIRED]
+// replace with ethernet shield mac. Must be unique for your network
+const byte mac[] = {0x90, 0xA2, 0xDA, 0x00, 0x53, 0xE5};
+
+/*==============================================================================
+ * CONFIGURATION ERROR CHECK (don't change anything here)
+ *============================================================================*/
+
+#if !defined WIZ5100_ETHERNET && !defined YUN_ETHERNET
+#error "you must define either WIZ5100_ETHERNET or YUN_ETHERNET in ethernetConfig.h"
+#endif
+
+#if defined remote_ip && defined remote_host
+#error "cannot define both remote_ip and remote_host at the same time in ethernetConfig.h"
+#endif
+
+/*==============================================================================
+ * PIN IGNORE MACROS (don't change anything here)
+ *============================================================================*/
+
+#if defined(WIZ5100_ETHERNET)
+
+// ignore SPI pins, pin 10 (Ethernet SS) and pin 4 (SS for SD-Card on Ethernet shield)
+#define IS_IGNORE_PIN(p) ((IS_PIN_SPI(p) || (p) == 4) || (p) == 10)
+
+#endif
--- /dev/null
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+\f
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
--- /dev/null
+/*
+ Firmata is a generic protocol for communicating with microcontrollers
+ from software on a host computer. It is intended to work with
+ any host computer software package.
+
+ To download a host software package, please click on the following link
+ to open the list of Firmata client libraries in your default browser.
+
+ https://github.com/firmata/arduino#firmata-client-libraries
+
+ Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.
+ Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved.
+ Copyright (C) 2009 Shigeru Kobayashi. All rights reserved.
+ Copyright (C) 2009-2016 Jeff Hoefs. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+
+ Last updated August 17th, 2017
+*/
+
+/*
+ README
+
+ StandardFirmataPlus adds additional features that may exceed the Flash and
+ RAM sizes of Arduino boards such as ATMega328p (Uno) and ATMega32u4
+ (Leonardo, Micro, Yun, etc). It is best to use StandardFirmataPlus with higher
+ memory boards such as the Arduino Mega, Arduino Due, Teensy 3.0/3.1/3.2.
+
+ All Firmata examples that are appended with "Plus" add the following features:
+
+ - Ability to interface with serial devices using UART, USART, or SoftwareSerial
+ depending on the capatilities of the board.
+
+ NOTE: In order to use SoftwareSerial with the Firmata Serial feature,
+ StandardFirmataPlus must be compiled with Arduino v1.6.6 or newer.
+
+ At the time of this writing, StandardFirmataPlus will still compile and run
+ on ATMega328p and ATMega32u4-based boards, but future versions of this sketch
+ may not as new features are added.
+*/
+
+#include <Servo.h>
+#include <Wire.h>
+#include <Firmata.h>
+
+// In order to use software serial, you will need to compile this sketch with
+// Arduino IDE v1.6.6 or higher. Hardware serial should work back to Arduino 1.0.
+#include "utility/SerialFirmata.h"
+
+#define I2C_WRITE B00000000
+#define I2C_READ B00001000
+#define I2C_READ_CONTINUOUSLY B00010000
+#define I2C_STOP_READING B00011000
+#define I2C_READ_WRITE_MODE_MASK B00011000
+#define I2C_10BIT_ADDRESS_MODE_MASK B00100000
+#define I2C_END_TX_MASK B01000000
+#define I2C_STOP_TX 1
+#define I2C_RESTART_TX 0
+#define I2C_MAX_QUERIES 8
+#define I2C_REGISTER_NOT_SPECIFIED -1
+
+// the minimum interval for sampling analog input
+#define MINIMUM_SAMPLING_INTERVAL 1
+
+
+/*==============================================================================
+ * GLOBAL VARIABLES
+ *============================================================================*/
+
+#ifdef FIRMATA_SERIAL_FEATURE
+SerialFirmata serialFeature;
+#endif
+
+/* analog inputs */
+int analogInputsToReport = 0; // bitwise array to store pin reporting
+
+/* digital input ports */
+byte reportPINs[TOTAL_PORTS]; // 1 = report this port, 0 = silence
+byte previousPINs[TOTAL_PORTS]; // previous 8 bits sent
+
+/* pins configuration */
+byte portConfigInputs[TOTAL_PORTS]; // each bit: 1 = pin in INPUT, 0 = anything else
+
+/* timer variables */
+unsigned long currentMillis; // store the current value from millis()
+unsigned long previousMillis; // for comparison with currentMillis
+unsigned int samplingInterval = 19; // how often to run the main loop (in ms)
+
+/* i2c data */
+struct i2c_device_info {
+ byte addr;
+ int reg;
+ byte bytes;
+ byte stopTX;
+};
+
+/* for i2c read continuous more */
+i2c_device_info query[I2C_MAX_QUERIES];
+
+byte i2cRxData[64];
+boolean isI2CEnabled = false;
+signed char queryIndex = -1;
+// default delay time between i2c read request and Wire.requestFrom()
+unsigned int i2cReadDelayTime = 0;
+
+Servo servos[MAX_SERVOS];
+byte servoPinMap[TOTAL_PINS];
+byte detachedServos[MAX_SERVOS];
+byte detachedServoCount = 0;
+byte servoCount = 0;
+
+boolean isResetting = false;
+
+// Forward declare a few functions to avoid compiler errors with older versions
+// of the Arduino IDE.
+void setPinModeCallback(byte, int);
+void reportAnalogCallback(byte analogPin, int value);
+void sysexCallback(byte, byte, byte*);
+
+/* utility functions */
+void wireWrite(byte data)
+{
+#if ARDUINO >= 100
+ Wire.write((byte)data);
+#else
+ Wire.send(data);
+#endif
+}
+
+byte wireRead(void)
+{
+#if ARDUINO >= 100
+ return Wire.read();
+#else
+ return Wire.receive();
+#endif
+}
+
+/*==============================================================================
+ * FUNCTIONS
+ *============================================================================*/
+
+void attachServo(byte pin, int minPulse, int maxPulse)
+{
+ if (servoCount < MAX_SERVOS) {
+ // reuse indexes of detached servos until all have been reallocated
+ if (detachedServoCount > 0) {
+ servoPinMap[pin] = detachedServos[detachedServoCount - 1];
+ if (detachedServoCount > 0) detachedServoCount--;
+ } else {
+ servoPinMap[pin] = servoCount;
+ servoCount++;
+ }
+ if (minPulse > 0 && maxPulse > 0) {
+ servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin), minPulse, maxPulse);
+ } else {
+ servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin));
+ }
+ } else {
+ Firmata.sendString("Max servos attached");
+ }
+}
+
+void detachServo(byte pin)
+{
+ servos[servoPinMap[pin]].detach();
+ // if we're detaching the last servo, decrement the count
+ // otherwise store the index of the detached servo
+ if (servoPinMap[pin] == servoCount && servoCount > 0) {
+ servoCount--;
+ } else if (servoCount > 0) {
+ // keep track of detached servos because we want to reuse their indexes
+ // before incrementing the count of attached servos
+ detachedServoCount++;
+ detachedServos[detachedServoCount - 1] = servoPinMap[pin];
+ }
+
+ servoPinMap[pin] = 255;
+}
+
+void enableI2CPins()
+{
+ byte i;
+ // is there a faster way to do this? would probaby require importing
+ // Arduino.h to get SCL and SDA pins
+ for (i = 0; i < TOTAL_PINS; i++) {
+ if (IS_PIN_I2C(i)) {
+ // mark pins as i2c so they are ignore in non i2c data requests
+ setPinModeCallback(i, PIN_MODE_I2C);
+ }
+ }
+
+ isI2CEnabled = true;
+
+ Wire.begin();
+}
+
+/* disable the i2c pins so they can be used for other functions */
+void disableI2CPins() {
+ isI2CEnabled = false;
+ // disable read continuous mode for all devices
+ queryIndex = -1;
+}
+
+void readAndReportData(byte address, int theRegister, byte numBytes, byte stopTX) {
+ // allow I2C requests that don't require a register read
+ // for example, some devices using an interrupt pin to signify new data available
+ // do not always require the register read so upon interrupt you call Wire.requestFrom()
+ if (theRegister != I2C_REGISTER_NOT_SPECIFIED) {
+ Wire.beginTransmission(address);
+ wireWrite((byte)theRegister);
+ Wire.endTransmission(stopTX); // default = true
+ // do not set a value of 0
+ if (i2cReadDelayTime > 0) {
+ // delay is necessary for some devices such as WiiNunchuck
+ delayMicroseconds(i2cReadDelayTime);
+ }
+ } else {
+ theRegister = 0; // fill the register with a dummy value
+ }
+
+ Wire.requestFrom(address, numBytes); // all bytes are returned in requestFrom
+
+ // check to be sure correct number of bytes were returned by slave
+ if (numBytes < Wire.available()) {
+ Firmata.sendString("I2C: Too many bytes received");
+ } else if (numBytes > Wire.available()) {
+ Firmata.sendString("I2C: Too few bytes received");
+ }
+
+ i2cRxData[0] = address;
+ i2cRxData[1] = theRegister;
+
+ for (int i = 0; i < numBytes && Wire.available(); i++) {
+ i2cRxData[2 + i] = wireRead();
+ }
+
+ // send slave address, register and received bytes
+ Firmata.sendSysex(SYSEX_I2C_REPLY, numBytes + 2, i2cRxData);
+}
+
+void outputPort(byte portNumber, byte portValue, byte forceSend)
+{
+ // pins not configured as INPUT are cleared to zeros
+ portValue = portValue & portConfigInputs[portNumber];
+ // only send if the value is different than previously sent
+ if (forceSend || previousPINs[portNumber] != portValue) {
+ Firmata.sendDigitalPort(portNumber, portValue);
+ previousPINs[portNumber] = portValue;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * check all the active digital inputs for change of state, then add any events
+ * to the Serial output queue using Serial.print() */
+void checkDigitalInputs(void)
+{
+ /* Using non-looping code allows constants to be given to readPort().
+ * The compiler will apply substantial optimizations if the inputs
+ * to readPort() are compile-time constants. */
+ if (TOTAL_PORTS > 0 && reportPINs[0]) outputPort(0, readPort(0, portConfigInputs[0]), false);
+ if (TOTAL_PORTS > 1 && reportPINs[1]) outputPort(1, readPort(1, portConfigInputs[1]), false);
+ if (TOTAL_PORTS > 2 && reportPINs[2]) outputPort(2, readPort(2, portConfigInputs[2]), false);
+ if (TOTAL_PORTS > 3 && reportPINs[3]) outputPort(3, readPort(3, portConfigInputs[3]), false);
+ if (TOTAL_PORTS > 4 && reportPINs[4]) outputPort(4, readPort(4, portConfigInputs[4]), false);
+ if (TOTAL_PORTS > 5 && reportPINs[5]) outputPort(5, readPort(5, portConfigInputs[5]), false);
+ if (TOTAL_PORTS > 6 && reportPINs[6]) outputPort(6, readPort(6, portConfigInputs[6]), false);
+ if (TOTAL_PORTS > 7 && reportPINs[7]) outputPort(7, readPort(7, portConfigInputs[7]), false);
+ if (TOTAL_PORTS > 8 && reportPINs[8]) outputPort(8, readPort(8, portConfigInputs[8]), false);
+ if (TOTAL_PORTS > 9 && reportPINs[9]) outputPort(9, readPort(9, portConfigInputs[9]), false);
+ if (TOTAL_PORTS > 10 && reportPINs[10]) outputPort(10, readPort(10, portConfigInputs[10]), false);
+ if (TOTAL_PORTS > 11 && reportPINs[11]) outputPort(11, readPort(11, portConfigInputs[11]), false);
+ if (TOTAL_PORTS > 12 && reportPINs[12]) outputPort(12, readPort(12, portConfigInputs[12]), false);
+ if (TOTAL_PORTS > 13 && reportPINs[13]) outputPort(13, readPort(13, portConfigInputs[13]), false);
+ if (TOTAL_PORTS > 14 && reportPINs[14]) outputPort(14, readPort(14, portConfigInputs[14]), false);
+ if (TOTAL_PORTS > 15 && reportPINs[15]) outputPort(15, readPort(15, portConfigInputs[15]), false);
+}
+
+// -----------------------------------------------------------------------------
+/* sets the pin mode to the correct state and sets the relevant bits in the
+ * two bit-arrays that track Digital I/O and PWM status
+ */
+void setPinModeCallback(byte pin, int mode)
+{
+ if (Firmata.getPinMode(pin) == PIN_MODE_IGNORE)
+ return;
+
+ if (Firmata.getPinMode(pin) == PIN_MODE_I2C && isI2CEnabled && mode != PIN_MODE_I2C) {
+ // disable i2c so pins can be used for other functions
+ // the following if statements should reconfigure the pins properly
+ disableI2CPins();
+ }
+ if (IS_PIN_DIGITAL(pin) && mode != PIN_MODE_SERVO) {
+ if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) {
+ detachServo(pin);
+ }
+ }
+ if (IS_PIN_ANALOG(pin)) {
+ reportAnalogCallback(PIN_TO_ANALOG(pin), mode == PIN_MODE_ANALOG ? 1 : 0); // turn on/off reporting
+ }
+ if (IS_PIN_DIGITAL(pin)) {
+ if (mode == INPUT || mode == PIN_MODE_PULLUP) {
+ portConfigInputs[pin / 8] |= (1 << (pin & 7));
+ } else {
+ portConfigInputs[pin / 8] &= ~(1 << (pin & 7));
+ }
+ }
+ Firmata.setPinState(pin, 0);
+ switch (mode) {
+ case PIN_MODE_ANALOG:
+ if (IS_PIN_ANALOG(pin)) {
+ if (IS_PIN_DIGITAL(pin)) {
+ pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
+#if ARDUINO <= 100
+ // deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6
+ digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
+#endif
+ }
+ Firmata.setPinMode(pin, PIN_MODE_ANALOG);
+ }
+ break;
+ case INPUT:
+ if (IS_PIN_DIGITAL(pin)) {
+ pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
+#if ARDUINO <= 100
+ // deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6
+ digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
+#endif
+ Firmata.setPinMode(pin, INPUT);
+ }
+ break;
+ case PIN_MODE_PULLUP:
+ if (IS_PIN_DIGITAL(pin)) {
+ pinMode(PIN_TO_DIGITAL(pin), INPUT_PULLUP);
+ Firmata.setPinMode(pin, PIN_MODE_PULLUP);
+ Firmata.setPinState(pin, 1);
+ }
+ break;
+ case OUTPUT:
+ if (IS_PIN_DIGITAL(pin)) {
+ if (Firmata.getPinMode(pin) == PIN_MODE_PWM) {
+ // Disable PWM if pin mode was previously set to PWM.
+ digitalWrite(PIN_TO_DIGITAL(pin), LOW);
+ }
+ pinMode(PIN_TO_DIGITAL(pin), OUTPUT);
+ Firmata.setPinMode(pin, OUTPUT);
+ }
+ break;
+ case PIN_MODE_PWM:
+ if (IS_PIN_PWM(pin)) {
+ pinMode(PIN_TO_PWM(pin), OUTPUT);
+ analogWrite(PIN_TO_PWM(pin), 0);
+ Firmata.setPinMode(pin, PIN_MODE_PWM);
+ }
+ break;
+ case PIN_MODE_SERVO:
+ if (IS_PIN_DIGITAL(pin)) {
+ Firmata.setPinMode(pin, PIN_MODE_SERVO);
+ if (servoPinMap[pin] == 255 || !servos[servoPinMap[pin]].attached()) {
+ // pass -1 for min and max pulse values to use default values set
+ // by Servo library
+ attachServo(pin, -1, -1);
+ }
+ }
+ break;
+ case PIN_MODE_I2C:
+ if (IS_PIN_I2C(pin)) {
+ // mark the pin as i2c
+ // the user must call I2C_CONFIG to enable I2C for a device
+ Firmata.setPinMode(pin, PIN_MODE_I2C);
+ }
+ break;
+ case PIN_MODE_SERIAL:
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.handlePinMode(pin, PIN_MODE_SERIAL);
+#endif
+ break;
+ default:
+ Firmata.sendString("Unknown pin mode"); // TODO: put error msgs in EEPROM
+ }
+ // TODO: save status to EEPROM here, if changed
+}
+
+/*
+ * Sets the value of an individual pin. Useful if you want to set a pin value but
+ * are not tracking the digital port state.
+ * Can only be used on pins configured as OUTPUT.
+ * Cannot be used to enable pull-ups on Digital INPUT pins.
+ */
+void setPinValueCallback(byte pin, int value)
+{
+ if (pin < TOTAL_PINS && IS_PIN_DIGITAL(pin)) {
+ if (Firmata.getPinMode(pin) == OUTPUT) {
+ Firmata.setPinState(pin, value);
+ digitalWrite(PIN_TO_DIGITAL(pin), value);
+ }
+ }
+}
+
+void analogWriteCallback(byte pin, int value)
+{
+ if (pin < TOTAL_PINS) {
+ switch (Firmata.getPinMode(pin)) {
+ case PIN_MODE_SERVO:
+ if (IS_PIN_DIGITAL(pin))
+ servos[servoPinMap[pin]].write(value);
+ Firmata.setPinState(pin, value);
+ break;
+ case PIN_MODE_PWM:
+ if (IS_PIN_PWM(pin))
+ analogWrite(PIN_TO_PWM(pin), value);
+ Firmata.setPinState(pin, value);
+ break;
+ }
+ }
+}
+
+void digitalWriteCallback(byte port, int value)
+{
+ byte pin, lastPin, pinValue, mask = 1, pinWriteMask = 0;
+
+ if (port < TOTAL_PORTS) {
+ // create a mask of the pins on this port that are writable.
+ lastPin = port * 8 + 8;
+ if (lastPin > TOTAL_PINS) lastPin = TOTAL_PINS;
+ for (pin = port * 8; pin < lastPin; pin++) {
+ // do not disturb non-digital pins (eg, Rx & Tx)
+ if (IS_PIN_DIGITAL(pin)) {
+ // do not touch pins in PWM, ANALOG, SERVO or other modes
+ if (Firmata.getPinMode(pin) == OUTPUT || Firmata.getPinMode(pin) == INPUT) {
+ pinValue = ((byte)value & mask) ? 1 : 0;
+ if (Firmata.getPinMode(pin) == OUTPUT) {
+ pinWriteMask |= mask;
+ } else if (Firmata.getPinMode(pin) == INPUT && pinValue == 1 && Firmata.getPinState(pin) != 1) {
+ // only handle INPUT here for backwards compatibility
+#if ARDUINO > 100
+ pinMode(pin, INPUT_PULLUP);
+#else
+ // only write to the INPUT pin to enable pullups if Arduino v1.0.0 or earlier
+ pinWriteMask |= mask;
+#endif
+ }
+ Firmata.setPinState(pin, pinValue);
+ }
+ }
+ mask = mask << 1;
+ }
+ writePort(port, (byte)value, pinWriteMask);
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+/* sets bits in a bit array (int) to toggle the reporting of the analogIns
+ */
+//void FirmataClass::setAnalogPinReporting(byte pin, byte state) {
+//}
+void reportAnalogCallback(byte analogPin, int value)
+{
+ if (analogPin < TOTAL_ANALOG_PINS) {
+ if (value == 0) {
+ analogInputsToReport = analogInputsToReport & ~ (1 << analogPin);
+ } else {
+ analogInputsToReport = analogInputsToReport | (1 << analogPin);
+ // prevent during system reset or all analog pin values will be reported
+ // which may report noise for unconnected analog pins
+ if (!isResetting) {
+ // Send pin value immediately. This is helpful when connected via
+ // ethernet, wi-fi or bluetooth so pin states can be known upon
+ // reconnecting.
+ Firmata.sendAnalog(analogPin, analogRead(analogPin));
+ }
+ }
+ }
+ // TODO: save status to EEPROM here, if changed
+}
+
+void reportDigitalCallback(byte port, int value)
+{
+ if (port < TOTAL_PORTS) {
+ reportPINs[port] = (byte)value;
+ // Send port value immediately. This is helpful when connected via
+ // ethernet, wi-fi or bluetooth so pin states can be known upon
+ // reconnecting.
+ if (value) outputPort(port, readPort(port, portConfigInputs[port]), true);
+ }
+ // do not disable analog reporting on these 8 pins, to allow some
+ // pins used for digital, others analog. Instead, allow both types
+ // of reporting to be enabled, but check if the pin is configured
+ // as analog when sampling the analog inputs. Likewise, while
+ // scanning digital pins, portConfigInputs will mask off values from any
+ // pins configured as analog
+}
+
+/*==============================================================================
+ * SYSEX-BASED commands
+ *============================================================================*/
+
+void sysexCallback(byte command, byte argc, byte *argv)
+{
+ byte mode;
+ byte stopTX;
+ byte slaveAddress;
+ byte data;
+ int slaveRegister;
+ unsigned int delayTime;
+
+ switch (command) {
+ case I2C_REQUEST:
+ mode = argv[1] & I2C_READ_WRITE_MODE_MASK;
+ if (argv[1] & I2C_10BIT_ADDRESS_MODE_MASK) {
+ Firmata.sendString("10-bit addressing not supported");
+ return;
+ }
+ else {
+ slaveAddress = argv[0];
+ }
+
+ // need to invert the logic here since 0 will be default for client
+ // libraries that have not updated to add support for restart tx
+ if (argv[1] & I2C_END_TX_MASK) {
+ stopTX = I2C_RESTART_TX;
+ }
+ else {
+ stopTX = I2C_STOP_TX; // default
+ }
+
+ switch (mode) {
+ case I2C_WRITE:
+ Wire.beginTransmission(slaveAddress);
+ for (byte i = 2; i < argc; i += 2) {
+ data = argv[i] + (argv[i + 1] << 7);
+ wireWrite(data);
+ }
+ Wire.endTransmission();
+ delayMicroseconds(70);
+ break;
+ case I2C_READ:
+ if (argc == 6) {
+ // a slave register is specified
+ slaveRegister = argv[2] + (argv[3] << 7);
+ data = argv[4] + (argv[5] << 7); // bytes to read
+ }
+ else {
+ // a slave register is NOT specified
+ slaveRegister = I2C_REGISTER_NOT_SPECIFIED;
+ data = argv[2] + (argv[3] << 7); // bytes to read
+ }
+ readAndReportData(slaveAddress, (int)slaveRegister, data, stopTX);
+ break;
+ case I2C_READ_CONTINUOUSLY:
+ if ((queryIndex + 1) >= I2C_MAX_QUERIES) {
+ // too many queries, just ignore
+ Firmata.sendString("too many queries");
+ break;
+ }
+ if (argc == 6) {
+ // a slave register is specified
+ slaveRegister = argv[2] + (argv[3] << 7);
+ data = argv[4] + (argv[5] << 7); // bytes to read
+ }
+ else {
+ // a slave register is NOT specified
+ slaveRegister = (int)I2C_REGISTER_NOT_SPECIFIED;
+ data = argv[2] + (argv[3] << 7); // bytes to read
+ }
+ queryIndex++;
+ query[queryIndex].addr = slaveAddress;
+ query[queryIndex].reg = slaveRegister;
+ query[queryIndex].bytes = data;
+ query[queryIndex].stopTX = stopTX;
+ break;
+ case I2C_STOP_READING:
+ byte queryIndexToSkip;
+ // if read continuous mode is enabled for only 1 i2c device, disable
+ // read continuous reporting for that device
+ if (queryIndex <= 0) {
+ queryIndex = -1;
+ } else {
+ queryIndexToSkip = 0;
+ // if read continuous mode is enabled for multiple devices,
+ // determine which device to stop reading and remove it's data from
+ // the array, shifiting other array data to fill the space
+ for (byte i = 0; i < queryIndex + 1; i++) {
+ if (query[i].addr == slaveAddress) {
+ queryIndexToSkip = i;
+ break;
+ }
+ }
+
+ for (byte i = queryIndexToSkip; i < queryIndex + 1; i++) {
+ if (i < I2C_MAX_QUERIES) {
+ query[i].addr = query[i + 1].addr;
+ query[i].reg = query[i + 1].reg;
+ query[i].bytes = query[i + 1].bytes;
+ query[i].stopTX = query[i + 1].stopTX;
+ }
+ }
+ queryIndex--;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case I2C_CONFIG:
+ delayTime = (argv[0] + (argv[1] << 7));
+
+ if (argc > 1 && delayTime > 0) {
+ i2cReadDelayTime = delayTime;
+ }
+
+ if (!isI2CEnabled) {
+ enableI2CPins();
+ }
+
+ break;
+ case SERVO_CONFIG:
+ if (argc > 4) {
+ // these vars are here for clarity, they'll optimized away by the compiler
+ byte pin = argv[0];
+ int minPulse = argv[1] + (argv[2] << 7);
+ int maxPulse = argv[3] + (argv[4] << 7);
+
+ if (IS_PIN_DIGITAL(pin)) {
+ if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) {
+ detachServo(pin);
+ }
+ attachServo(pin, minPulse, maxPulse);
+ setPinModeCallback(pin, PIN_MODE_SERVO);
+ }
+ }
+ break;
+ case SAMPLING_INTERVAL:
+ if (argc > 1) {
+ samplingInterval = argv[0] + (argv[1] << 7);
+ if (samplingInterval < MINIMUM_SAMPLING_INTERVAL) {
+ samplingInterval = MINIMUM_SAMPLING_INTERVAL;
+ }
+ } else {
+ //Firmata.sendString("Not enough data");
+ }
+ break;
+ case EXTENDED_ANALOG:
+ if (argc > 1) {
+ int val = argv[1];
+ if (argc > 2) val |= (argv[2] << 7);
+ if (argc > 3) val |= (argv[3] << 14);
+ analogWriteCallback(argv[0], val);
+ }
+ break;
+ case CAPABILITY_QUERY:
+ Firmata.write(START_SYSEX);
+ Firmata.write(CAPABILITY_RESPONSE);
+ for (byte pin = 0; pin < TOTAL_PINS; pin++) {
+ if (IS_PIN_DIGITAL(pin)) {
+ Firmata.write((byte)INPUT);
+ Firmata.write(1);
+ Firmata.write((byte)PIN_MODE_PULLUP);
+ Firmata.write(1);
+ Firmata.write((byte)OUTPUT);
+ Firmata.write(1);
+ }
+ if (IS_PIN_ANALOG(pin)) {
+ Firmata.write(PIN_MODE_ANALOG);
+ Firmata.write(10); // 10 = 10-bit resolution
+ }
+ if (IS_PIN_PWM(pin)) {
+ Firmata.write(PIN_MODE_PWM);
+ Firmata.write(DEFAULT_PWM_RESOLUTION);
+ }
+ if (IS_PIN_DIGITAL(pin)) {
+ Firmata.write(PIN_MODE_SERVO);
+ Firmata.write(14);
+ }
+ if (IS_PIN_I2C(pin)) {
+ Firmata.write(PIN_MODE_I2C);
+ Firmata.write(1); // TODO: could assign a number to map to SCL or SDA
+ }
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.handleCapability(pin);
+#endif
+ Firmata.write(127);
+ }
+ Firmata.write(END_SYSEX);
+ break;
+ case PIN_STATE_QUERY:
+ if (argc > 0) {
+ byte pin = argv[0];
+ Firmata.write(START_SYSEX);
+ Firmata.write(PIN_STATE_RESPONSE);
+ Firmata.write(pin);
+ if (pin < TOTAL_PINS) {
+ Firmata.write(Firmata.getPinMode(pin));
+ Firmata.write((byte)Firmata.getPinState(pin) & 0x7F);
+ if (Firmata.getPinState(pin) & 0xFF80) Firmata.write((byte)(Firmata.getPinState(pin) >> 7) & 0x7F);
+ if (Firmata.getPinState(pin) & 0xC000) Firmata.write((byte)(Firmata.getPinState(pin) >> 14) & 0x7F);
+ }
+ Firmata.write(END_SYSEX);
+ }
+ break;
+ case ANALOG_MAPPING_QUERY:
+ Firmata.write(START_SYSEX);
+ Firmata.write(ANALOG_MAPPING_RESPONSE);
+ for (byte pin = 0; pin < TOTAL_PINS; pin++) {
+ Firmata.write(IS_PIN_ANALOG(pin) ? PIN_TO_ANALOG(pin) : 127);
+ }
+ Firmata.write(END_SYSEX);
+ break;
+
+ case SERIAL_MESSAGE:
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.handleSysex(command, argc, argv);
+#endif
+ break;
+ }
+}
+
+/*==============================================================================
+ * SETUP()
+ *============================================================================*/
+
+void systemResetCallback()
+{
+ isResetting = true;
+
+ // initialize a defalt state
+ // TODO: option to load config from EEPROM instead of default
+
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.reset();
+#endif
+
+ if (isI2CEnabled) {
+ disableI2CPins();
+ }
+
+ for (byte i = 0; i < TOTAL_PORTS; i++) {
+ reportPINs[i] = false; // by default, reporting off
+ portConfigInputs[i] = 0; // until activated
+ previousPINs[i] = 0;
+ }
+
+ for (byte i = 0; i < TOTAL_PINS; i++) {
+ // pins with analog capability default to analog input
+ // otherwise, pins default to digital output
+ if (IS_PIN_ANALOG(i)) {
+ // turns off pullup, configures everything
+ setPinModeCallback(i, PIN_MODE_ANALOG);
+ } else if (IS_PIN_DIGITAL(i)) {
+ // sets the output to 0, configures portConfigInputs
+ setPinModeCallback(i, OUTPUT);
+ }
+
+ servoPinMap[i] = 255;
+ }
+ // by default, do not report any analog inputs
+ analogInputsToReport = 0;
+
+ detachedServoCount = 0;
+ servoCount = 0;
+
+ /* send digital inputs to set the initial state on the host computer,
+ * since once in the loop(), this firmware will only send on change */
+ /*
+ TODO: this can never execute, since no pins default to digital input
+ but it will be needed when/if we support EEPROM stored config
+ for (byte i=0; i < TOTAL_PORTS; i++) {
+ outputPort(i, readPort(i, portConfigInputs[i]), true);
+ }
+ */
+ isResetting = false;
+}
+
+void setup()
+{
+ Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
+
+ Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
+ Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
+ Firmata.attach(REPORT_ANALOG, reportAnalogCallback);
+ Firmata.attach(REPORT_DIGITAL, reportDigitalCallback);
+ Firmata.attach(SET_PIN_MODE, setPinModeCallback);
+ Firmata.attach(SET_DIGITAL_PIN_VALUE, setPinValueCallback);
+ Firmata.attach(START_SYSEX, sysexCallback);
+ Firmata.attach(SYSTEM_RESET, systemResetCallback);
+
+ // Save a couple of seconds by disabling the startup blink sequence.
+ Firmata.disableBlinkVersion();
+
+ // to use a port other than Serial, such as Serial1 on an Arduino Leonardo or Mega,
+ // Call begin(baud) on the alternate serial port and pass it to Firmata to begin like this:
+ // Serial1.begin(57600);
+ // Firmata.begin(Serial1);
+ // However do not do this if you are using SERIAL_MESSAGE
+
+ Firmata.begin(57600);
+ while (!Serial) {
+ ; // wait for serial port to connect. Needed for ATmega32u4-based boards and Arduino 101
+ }
+
+ systemResetCallback(); // reset to default config
+}
+
+/*==============================================================================
+ * LOOP()
+ *============================================================================*/
+void loop()
+{
+ byte pin, analogPin;
+
+ /* DIGITALREAD - as fast as possible, check for changes and output them to the
+ * FTDI buffer using Serial.print() */
+ checkDigitalInputs();
+
+ /* STREAMREAD - processing incoming messagse as soon as possible, while still
+ * checking digital inputs. */
+ while (Firmata.available())
+ Firmata.processInput();
+
+ // TODO - ensure that Stream buffer doesn't go over 60 bytes
+
+ currentMillis = millis();
+ if (currentMillis - previousMillis > samplingInterval) {
+ previousMillis += samplingInterval;
+ /* ANALOGREAD - do all analogReads() at the configured sampling interval */
+ for (pin = 0; pin < TOTAL_PINS; pin++) {
+ if (IS_PIN_ANALOG(pin) && Firmata.getPinMode(pin) == PIN_MODE_ANALOG) {
+ analogPin = PIN_TO_ANALOG(pin);
+ if (analogInputsToReport & (1 << analogPin)) {
+ Firmata.sendAnalog(analogPin, analogRead(analogPin));
+ }
+ }
+ }
+ // report i2c data for all device with read continuous mode enabled
+ if (queryIndex > -1) {
+ for (byte i = 0; i < queryIndex + 1; i++) {
+ readAndReportData(query[i].addr, query[i].reg, query[i].bytes, query[i].stopTX);
+ }
+ }
+ }
+
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.update();
+#endif
+}
--- /dev/null
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+\f
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
--- /dev/null
+/*
+ Firmata is a generic protocol for communicating with microcontrollers
+ from software on a host computer. It is intended to work with
+ any host computer software package.
+
+ To download a host software package, please click on the following link
+ to open the list of Firmata client libraries in your default browser.
+
+ https://github.com/firmata/arduino#firmata-client-libraries
+
+ Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.
+ Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved.
+ Copyright (C) 2009 Shigeru Kobayashi. All rights reserved.
+ Copyright (C) 2009-2016 Jeff Hoefs. All rights reserved.
+ Copyright (C) 2015-2016 Jesse Frush. All rights reserved.
+ Copyright (C) 2016 Jens B. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+
+ Last updated August 17th, 2017
+*/
+
+/*
+ README
+
+ StandardFirmataWiFi enables the use of Firmata over a TCP connection. It can be configured as
+ either a TCP server or TCP client.
+
+ To use StandardFirmataWiFi you will need to have one of the following
+ boards or shields:
+
+ - Arduino WiFi Shield (or clone)
+ - Arduino WiFi Shield 101
+ - Arduino MKR1000 board
+ - ESP8266 WiFi board compatible with ESP8266 Arduino core
+
+ Follow the instructions in the wifiConfig.h file (wifiConfig.h tab in Arduino IDE) to
+ configure your particular hardware.
+
+ Dependencies:
+ - WiFi Shield 101 requires version 0.7.0 or higher of the WiFi101 library (available in Arduino
+ 1.6.8 or higher, or update the library via the Arduino Library Manager or clone from source:
+ https://github.com/arduino-libraries/WiFi101)
+ - ESP8266 requires the Arduino ESP8266 core v2.1.0 or higher which can be obtained here:
+ https://github.com/esp8266/Arduino
+
+ In order to use the WiFi Shield 101 with Firmata you will need a board with at least 35k of Flash
+ memory. This means you cannot use the WiFi Shield 101 with an Arduino Uno or any other
+ ATmega328p-based microcontroller or with an Arduino Leonardo or other ATmega32u4-based
+ microcontroller. Some boards that will work are:
+
+ - Arduino Zero
+ - Arduino Due
+ - Arduino 101
+ - Arduino Mega
+
+ NOTE: If you are using an Arduino WiFi (legacy) shield you cannot use the following pins on
+ the following boards. Firmata will ignore any requests to use these pins:
+
+ - Arduino Uno or other ATMega328 boards: (D4, D7, D10, D11, D12, D13)
+ - Arduino Mega: (D4, D7, D10, D50, D51, D52, D53)
+ - Arduino Due, Zero or Leonardo: (D4, D7, D10)
+
+ If you are using an Arduino WiFi 101 shield you cannot use the following pins on the following
+ boards:
+
+ - Arduino Due or Zero: (D5, D7, D10)
+ - Arduino Mega: (D5, D7, D10, D50, D52, D53)
+*/
+
+#include <Servo.h>
+#include <Wire.h>
+#include <Firmata.h>
+
+/*
+ * Uncomment the #define SERIAL_DEBUG line below to receive serial output messages relating to your
+ * connection that may help in the event of connection issues. If defined, some boards may not begin
+ * executing this sketch until the Serial console is opened.
+ */
+//#define SERIAL_DEBUG
+#include "utility/firmataDebug.h"
+
+/*
+ * Uncomment the following include to enable interfacing with Serial devices via hardware or
+ * software serial.
+ */
+// In order to use software serial, you will need to compile this sketch with
+// Arduino IDE v1.6.6 or higher. Hardware serial should work back to Arduino 1.0.
+//#include "utility/SerialFirmata.h"
+
+// follow the instructions in wifiConfig.h to configure your particular hardware
+#include "wifiConfig.h"
+
+#define I2C_WRITE B00000000
+#define I2C_READ B00001000
+#define I2C_READ_CONTINUOUSLY B00010000
+#define I2C_STOP_READING B00011000
+#define I2C_READ_WRITE_MODE_MASK B00011000
+#define I2C_10BIT_ADDRESS_MODE_MASK B00100000
+#define I2C_END_TX_MASK B01000000
+#define I2C_STOP_TX 1
+#define I2C_RESTART_TX 0
+#define I2C_MAX_QUERIES 8
+#define I2C_REGISTER_NOT_SPECIFIED -1
+
+// the minimum interval for sampling analog input
+#define MINIMUM_SAMPLING_INTERVAL 1
+
+#define MAX_CONN_ATTEMPTS 20 // [500 ms] -> 10 s
+
+/*==============================================================================
+ * GLOBAL VARIABLES
+ *============================================================================*/
+
+#ifdef FIRMATA_SERIAL_FEATURE
+SerialFirmata serialFeature;
+#endif
+
+#ifdef STATIC_IP_ADDRESS
+IPAddress local_ip(STATIC_IP_ADDRESS);
+#endif
+#ifdef SUBNET_MASK
+IPAddress subnet(SUBNET_MASK);
+#endif
+#ifdef GATEWAY_IP_ADDRESS
+IPAddress gateway(GATEWAY_IP_ADDRESS);
+#endif
+
+int connectionAttempts = 0;
+bool streamConnected = false;
+
+/* analog inputs */
+int analogInputsToReport = 0; // bitwise array to store pin reporting
+
+/* digital input ports */
+byte reportPINs[TOTAL_PORTS]; // 1 = report this port, 0 = silence
+byte previousPINs[TOTAL_PORTS]; // previous 8 bits sent
+
+/* pins configuration */
+byte portConfigInputs[TOTAL_PORTS]; // each bit: 1 = pin in INPUT, 0 = anything else
+
+/* timer variables */
+unsigned long currentMillis; // store the current value from millis()
+unsigned long previousMillis; // for comparison with currentMillis
+unsigned int samplingInterval = 19; // how often to sample analog inputs (in ms)
+
+/* i2c data */
+struct i2c_device_info {
+ byte addr;
+ int reg;
+ byte bytes;
+ byte stopTX;
+};
+
+/* for i2c read continuous mode */
+i2c_device_info query[I2C_MAX_QUERIES];
+
+byte i2cRxData[64];
+boolean isI2CEnabled = false;
+signed char queryIndex = -1;
+// default delay time between i2c read request and Wire.requestFrom()
+unsigned int i2cReadDelayTime = 0;
+
+Servo servos[MAX_SERVOS];
+byte servoPinMap[TOTAL_PINS];
+byte detachedServos[MAX_SERVOS];
+byte detachedServoCount = 0;
+byte servoCount = 0;
+
+boolean isResetting = false;
+
+// Forward declare a few functions to avoid compiler errors with older versions
+// of the Arduino IDE.
+void setPinModeCallback(byte, int);
+void reportAnalogCallback(byte analogPin, int value);
+void sysexCallback(byte, byte, byte*);
+
+/* utility functions */
+void wireWrite(byte data)
+{
+#if ARDUINO >= 100
+ Wire.write((byte)data);
+#else
+ Wire.send(data);
+#endif
+}
+
+byte wireRead(void)
+{
+#if ARDUINO >= 100
+ return Wire.read();
+#else
+ return Wire.receive();
+#endif
+}
+
+/*==============================================================================
+ * FUNCTIONS
+ *============================================================================*/
+
+void attachServo(byte pin, int minPulse, int maxPulse)
+{
+ if (servoCount < MAX_SERVOS) {
+ // reuse indexes of detached servos until all have been reallocated
+ if (detachedServoCount > 0) {
+ servoPinMap[pin] = detachedServos[detachedServoCount - 1];
+ if (detachedServoCount > 0) detachedServoCount--;
+ } else {
+ servoPinMap[pin] = servoCount;
+ servoCount++;
+ }
+ if (minPulse > 0 && maxPulse > 0) {
+ servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin), minPulse, maxPulse);
+ } else {
+ servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin));
+ }
+ } else {
+ Firmata.sendString("Max servos attached");
+ }
+}
+
+void detachServo(byte pin)
+{
+ servos[servoPinMap[pin]].detach();
+ // if we're detaching the last servo, decrement the count
+ // otherwise store the index of the detached servo
+ if (servoPinMap[pin] == servoCount && servoCount > 0) {
+ servoCount--;
+ } else if (servoCount > 0) {
+ // keep track of detached servos because we want to reuse their indexes
+ // before incrementing the count of attached servos
+ detachedServoCount++;
+ detachedServos[detachedServoCount - 1] = servoPinMap[pin];
+ }
+
+ servoPinMap[pin] = 255;
+}
+
+void enableI2CPins()
+{
+ byte i;
+ // is there a faster way to do this? would probaby require importing
+ // Arduino.h to get SCL and SDA pins
+ for (i = 0; i < TOTAL_PINS; i++) {
+ if (IS_PIN_I2C(i)) {
+ // mark pins as i2c so they are ignore in non i2c data requests
+ setPinModeCallback(i, PIN_MODE_I2C);
+ }
+ }
+
+ isI2CEnabled = true;
+
+ Wire.begin();
+}
+
+/* disable the i2c pins so they can be used for other functions */
+void disableI2CPins() {
+ isI2CEnabled = false;
+ // disable read continuous mode for all devices
+ queryIndex = -1;
+}
+
+void readAndReportData(byte address, int theRegister, byte numBytes, byte stopTX) {
+ // allow I2C requests that don't require a register read
+ // for example, some devices using an interrupt pin to signify new data available
+ // do not always require the register read so upon interrupt you call Wire.requestFrom()
+ if (theRegister != I2C_REGISTER_NOT_SPECIFIED) {
+ Wire.beginTransmission(address);
+ wireWrite((byte)theRegister);
+ Wire.endTransmission(stopTX); // default = true
+ // do not set a value of 0
+ if (i2cReadDelayTime > 0) {
+ // delay is necessary for some devices such as WiiNunchuck
+ delayMicroseconds(i2cReadDelayTime);
+ }
+ } else {
+ theRegister = 0; // fill the register with a dummy value
+ }
+
+ Wire.requestFrom(address, numBytes); // all bytes are returned in requestFrom
+
+ // check to be sure correct number of bytes were returned by slave
+ if (numBytes < Wire.available()) {
+ Firmata.sendString("I2C: Too many bytes received");
+ } else if (numBytes > Wire.available()) {
+ Firmata.sendString("I2C: Too few bytes received");
+ }
+
+ i2cRxData[0] = address;
+ i2cRxData[1] = theRegister;
+
+ for (int i = 0; i < numBytes && Wire.available(); i++) {
+ i2cRxData[2 + i] = wireRead();
+ }
+
+ // send slave address, register and received bytes
+ Firmata.sendSysex(SYSEX_I2C_REPLY, numBytes + 2, i2cRxData);
+}
+
+void outputPort(byte portNumber, byte portValue, byte forceSend)
+{
+ // pins not configured as INPUT are cleared to zeros
+ portValue = portValue & portConfigInputs[portNumber];
+ // only send if the value is different than previously sent
+ if (forceSend || previousPINs[portNumber] != portValue) {
+ Firmata.sendDigitalPort(portNumber, portValue);
+ previousPINs[portNumber] = portValue;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * check all the active digital inputs for change of state, then add any events
+ * to the Stream output queue using Stream.write() */
+void checkDigitalInputs(void)
+{
+ /* Using non-looping code allows constants to be given to readPort().
+ * The compiler will apply substantial optimizations if the inputs
+ * to readPort() are compile-time constants. */
+ if (TOTAL_PORTS > 0 && reportPINs[0]) outputPort(0, readPort(0, portConfigInputs[0]), false);
+ if (TOTAL_PORTS > 1 && reportPINs[1]) outputPort(1, readPort(1, portConfigInputs[1]), false);
+ if (TOTAL_PORTS > 2 && reportPINs[2]) outputPort(2, readPort(2, portConfigInputs[2]), false);
+ if (TOTAL_PORTS > 3 && reportPINs[3]) outputPort(3, readPort(3, portConfigInputs[3]), false);
+ if (TOTAL_PORTS > 4 && reportPINs[4]) outputPort(4, readPort(4, portConfigInputs[4]), false);
+ if (TOTAL_PORTS > 5 && reportPINs[5]) outputPort(5, readPort(5, portConfigInputs[5]), false);
+ if (TOTAL_PORTS > 6 && reportPINs[6]) outputPort(6, readPort(6, portConfigInputs[6]), false);
+ if (TOTAL_PORTS > 7 && reportPINs[7]) outputPort(7, readPort(7, portConfigInputs[7]), false);
+ if (TOTAL_PORTS > 8 && reportPINs[8]) outputPort(8, readPort(8, portConfigInputs[8]), false);
+ if (TOTAL_PORTS > 9 && reportPINs[9]) outputPort(9, readPort(9, portConfigInputs[9]), false);
+ if (TOTAL_PORTS > 10 && reportPINs[10]) outputPort(10, readPort(10, portConfigInputs[10]), false);
+ if (TOTAL_PORTS > 11 && reportPINs[11]) outputPort(11, readPort(11, portConfigInputs[11]), false);
+ if (TOTAL_PORTS > 12 && reportPINs[12]) outputPort(12, readPort(12, portConfigInputs[12]), false);
+ if (TOTAL_PORTS > 13 && reportPINs[13]) outputPort(13, readPort(13, portConfigInputs[13]), false);
+ if (TOTAL_PORTS > 14 && reportPINs[14]) outputPort(14, readPort(14, portConfigInputs[14]), false);
+ if (TOTAL_PORTS > 15 && reportPINs[15]) outputPort(15, readPort(15, portConfigInputs[15]), false);
+}
+
+// -----------------------------------------------------------------------------
+// function forward declarations for xtensa compiler (ESP8266)
+void enableI2CPins();
+void disableI2CPins();
+void reportAnalogCallback(byte analogPin, int value);
+
+// -----------------------------------------------------------------------------
+/* sets the pin mode to the correct state and sets the relevant bits in the
+ * two bit-arrays that track Digital I/O and PWM status
+ */
+void setPinModeCallback(byte pin, int mode)
+{
+ if (Firmata.getPinMode(pin) == PIN_MODE_IGNORE)
+ return;
+
+ if (Firmata.getPinMode(pin) == PIN_MODE_I2C && isI2CEnabled && mode != PIN_MODE_I2C) {
+ // disable i2c so pins can be used for other functions
+ // the following if statements should reconfigure the pins properly
+ disableI2CPins();
+ }
+ if (IS_PIN_DIGITAL(pin) && mode != PIN_MODE_SERVO) {
+ if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) {
+ detachServo(pin);
+ }
+ }
+ if (IS_PIN_ANALOG(pin)) {
+ reportAnalogCallback(PIN_TO_ANALOG(pin), mode == PIN_MODE_ANALOG ? 1 : 0); // turn on/off reporting
+ }
+ if (IS_PIN_DIGITAL(pin)) {
+ if (mode == INPUT || mode == PIN_MODE_PULLUP) {
+ portConfigInputs[pin / 8] |= (1 << (pin & 7));
+ } else {
+ portConfigInputs[pin / 8] &= ~(1 << (pin & 7));
+ }
+ }
+ Firmata.setPinState(pin, 0);
+ switch (mode) {
+ case PIN_MODE_ANALOG:
+ if (IS_PIN_ANALOG(pin)) {
+ if (IS_PIN_DIGITAL(pin)) {
+ pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
+#if ARDUINO <= 100
+ // deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6
+ digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
+#endif
+ }
+ Firmata.setPinMode(pin, PIN_MODE_ANALOG);
+ }
+ break;
+ case INPUT:
+ if (IS_PIN_DIGITAL(pin)) {
+ pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
+#if ARDUINO <= 100
+ // deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6
+ digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
+#endif
+ Firmata.setPinMode(pin, INPUT);
+ }
+ break;
+ case PIN_MODE_PULLUP:
+ if (IS_PIN_DIGITAL(pin)) {
+ pinMode(PIN_TO_DIGITAL(pin), INPUT_PULLUP);
+ Firmata.setPinMode(pin, PIN_MODE_PULLUP);
+ Firmata.setPinState(pin, 1);
+ }
+ break;
+ case OUTPUT:
+ if (IS_PIN_DIGITAL(pin)) {
+ if (Firmata.getPinMode(pin) == PIN_MODE_PWM) {
+ // Disable PWM if pin mode was previously set to PWM.
+ digitalWrite(PIN_TO_DIGITAL(pin), LOW);
+ }
+ pinMode(PIN_TO_DIGITAL(pin), OUTPUT);
+ Firmata.setPinMode(pin, OUTPUT);
+ }
+ break;
+ case PIN_MODE_PWM:
+ if (IS_PIN_PWM(pin)) {
+ pinMode(PIN_TO_PWM(pin), OUTPUT);
+ analogWrite(PIN_TO_PWM(pin), 0);
+ Firmata.setPinMode(pin, PIN_MODE_PWM);
+ }
+ break;
+ case PIN_MODE_SERVO:
+ if (IS_PIN_DIGITAL(pin)) {
+ Firmata.setPinMode(pin, PIN_MODE_SERVO);
+ if (servoPinMap[pin] == 255 || !servos[servoPinMap[pin]].attached()) {
+ // pass -1 for min and max pulse values to use default values set
+ // by Servo library
+ attachServo(pin, -1, -1);
+ }
+ }
+ break;
+ case PIN_MODE_I2C:
+ if (IS_PIN_I2C(pin)) {
+ // mark the pin as i2c
+ // the user must call I2C_CONFIG to enable I2C for a device
+ Firmata.setPinMode(pin, PIN_MODE_I2C);
+ }
+ break;
+ case PIN_MODE_SERIAL:
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.handlePinMode(pin, PIN_MODE_SERIAL);
+#endif
+ break;
+ default:
+ Firmata.sendString("Unknown pin mode"); // TODO: put error msgs in EEPROM
+ }
+ // TODO: save status to EEPROM here, if changed
+}
+
+/*
+ * Sets the value of an individual pin. Useful if you want to set a pin value but
+ * are not tracking the digital port state.
+ * Can only be used on pins configured as OUTPUT.
+ * Cannot be used to enable pull-ups on Digital INPUT pins.
+ */
+void setPinValueCallback(byte pin, int value)
+{
+ if (pin < TOTAL_PINS && IS_PIN_DIGITAL(pin)) {
+ if (Firmata.getPinMode(pin) == OUTPUT) {
+ Firmata.setPinState(pin, value);
+ digitalWrite(PIN_TO_DIGITAL(pin), value);
+ }
+ }
+}
+
+void analogWriteCallback(byte pin, int value)
+{
+ if (pin < TOTAL_PINS) {
+ switch (Firmata.getPinMode(pin)) {
+ case PIN_MODE_SERVO:
+ if (IS_PIN_DIGITAL(pin))
+ servos[servoPinMap[pin]].write(value);
+ Firmata.setPinState(pin, value);
+ break;
+ case PIN_MODE_PWM:
+ if (IS_PIN_PWM(pin))
+ analogWrite(PIN_TO_PWM(pin), value);
+ Firmata.setPinState(pin, value);
+ break;
+ }
+ }
+}
+
+void digitalWriteCallback(byte port, int value)
+{
+ byte pin, lastPin, pinValue, mask = 1, pinWriteMask = 0;
+
+ if (port < TOTAL_PORTS) {
+ // create a mask of the pins on this port that are writable.
+ lastPin = port * 8 + 8;
+ if (lastPin > TOTAL_PINS) lastPin = TOTAL_PINS;
+ for (pin = port * 8; pin < lastPin; pin++) {
+ // do not disturb non-digital pins (eg, Rx & Tx)
+ if (IS_PIN_DIGITAL(pin)) {
+ // do not touch pins in PWM, ANALOG, SERVO or other modes
+ if (Firmata.getPinMode(pin) == OUTPUT || Firmata.getPinMode(pin) == INPUT) {
+ pinValue = ((byte)value & mask) ? 1 : 0;
+ if (Firmata.getPinMode(pin) == OUTPUT) {
+ pinWriteMask |= mask;
+ } else if (Firmata.getPinMode(pin) == INPUT && pinValue == 1 && Firmata.getPinState(pin) != 1) {
+ // only handle INPUT here for backwards compatibility
+#if ARDUINO > 100
+ pinMode(pin, INPUT_PULLUP);
+#else
+ // only write to the INPUT pin to enable pullups if Arduino v1.0.0 or earlier
+ pinWriteMask |= mask;
+#endif
+ }
+ Firmata.setPinState(pin, pinValue);
+ }
+ }
+ mask = mask << 1;
+ }
+ writePort(port, (byte)value, pinWriteMask);
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+/* sets bits in a bit array (int) to toggle the reporting of the analogIns
+ */
+//void FirmataClass::setAnalogPinReporting(byte pin, byte state) {
+//}
+void reportAnalogCallback(byte analogPin, int value)
+{
+ if (analogPin < TOTAL_ANALOG_PINS) {
+ if (value == 0) {
+ analogInputsToReport = analogInputsToReport & ~ (1 << analogPin);
+ } else {
+ analogInputsToReport = analogInputsToReport | (1 << analogPin);
+ // prevent during system reset or all analog pin values will be reported
+ // which may report noise for unconnected analog pins
+ if (!isResetting) {
+ // Send pin value immediately. This is helpful when connected via
+ // ethernet, wi-fi or bluetooth so pin states can be known upon
+ // reconnecting.
+ Firmata.sendAnalog(analogPin, analogRead(analogPin));
+ }
+ }
+ }
+ // TODO: save status to EEPROM here, if changed
+}
+
+void reportDigitalCallback(byte port, int value)
+{
+ if (port < TOTAL_PORTS) {
+ reportPINs[port] = (byte)value;
+ // Send port value immediately. This is helpful when connected via
+ // ethernet, wi-fi or bluetooth so pin states can be known upon
+ // reconnecting.
+ if (value) outputPort(port, readPort(port, portConfigInputs[port]), true);
+ }
+ // do not disable analog reporting on these 8 pins, to allow some
+ // pins used for digital, others analog. Instead, allow both types
+ // of reporting to be enabled, but check if the pin is configured
+ // as analog when sampling the analog inputs. Likewise, while
+ // scanning digital pins, portConfigInputs will mask off values from any
+ // pins configured as analog
+}
+
+/*==============================================================================
+ * SYSEX-BASED commands
+ *============================================================================*/
+
+void sysexCallback(byte command, byte argc, byte *argv)
+{
+ byte mode;
+ byte stopTX;
+ byte slaveAddress;
+ byte data;
+ int slaveRegister;
+ unsigned int delayTime;
+
+ switch (command) {
+ case I2C_REQUEST:
+ mode = argv[1] & I2C_READ_WRITE_MODE_MASK;
+ if (argv[1] & I2C_10BIT_ADDRESS_MODE_MASK) {
+ Firmata.sendString("10-bit addressing not supported");
+ return;
+ }
+ else {
+ slaveAddress = argv[0];
+ }
+
+ // need to invert the logic here since 0 will be default for client
+ // libraries that have not updated to add support for restart tx
+ if (argv[1] & I2C_END_TX_MASK) {
+ stopTX = I2C_RESTART_TX;
+ }
+ else {
+ stopTX = I2C_STOP_TX; // default
+ }
+
+ switch (mode) {
+ case I2C_WRITE:
+ Wire.beginTransmission(slaveAddress);
+ for (byte i = 2; i < argc; i += 2) {
+ data = argv[i] + (argv[i + 1] << 7);
+ wireWrite(data);
+ }
+ Wire.endTransmission();
+ delayMicroseconds(70);
+ break;
+ case I2C_READ:
+ if (argc == 6) {
+ // a slave register is specified
+ slaveRegister = argv[2] + (argv[3] << 7);
+ data = argv[4] + (argv[5] << 7); // bytes to read
+ }
+ else {
+ // a slave register is NOT specified
+ slaveRegister = I2C_REGISTER_NOT_SPECIFIED;
+ data = argv[2] + (argv[3] << 7); // bytes to read
+ }
+ readAndReportData(slaveAddress, (int)slaveRegister, data, stopTX);
+ break;
+ case I2C_READ_CONTINUOUSLY:
+ if ((queryIndex + 1) >= I2C_MAX_QUERIES) {
+ // too many queries, just ignore
+ Firmata.sendString("too many queries");
+ break;
+ }
+ if (argc == 6) {
+ // a slave register is specified
+ slaveRegister = argv[2] + (argv[3] << 7);
+ data = argv[4] + (argv[5] << 7); // bytes to read
+ }
+ else {
+ // a slave register is NOT specified
+ slaveRegister = (int)I2C_REGISTER_NOT_SPECIFIED;
+ data = argv[2] + (argv[3] << 7); // bytes to read
+ }
+ queryIndex++;
+ query[queryIndex].addr = slaveAddress;
+ query[queryIndex].reg = slaveRegister;
+ query[queryIndex].bytes = data;
+ query[queryIndex].stopTX = stopTX;
+ break;
+ case I2C_STOP_READING:
+ byte queryIndexToSkip;
+ // if read continuous mode is enabled for only 1 i2c device, disable
+ // read continuous reporting for that device
+ if (queryIndex <= 0) {
+ queryIndex = -1;
+ } else {
+ queryIndexToSkip = 0;
+ // if read continuous mode is enabled for multiple devices,
+ // determine which device to stop reading and remove it's data from
+ // the array, shifiting other array data to fill the space
+ for (byte i = 0; i < queryIndex + 1; i++) {
+ if (query[i].addr == slaveAddress) {
+ queryIndexToSkip = i;
+ break;
+ }
+ }
+
+ for (byte i = queryIndexToSkip; i < queryIndex + 1; i++) {
+ if (i < I2C_MAX_QUERIES) {
+ query[i].addr = query[i + 1].addr;
+ query[i].reg = query[i + 1].reg;
+ query[i].bytes = query[i + 1].bytes;
+ query[i].stopTX = query[i + 1].stopTX;
+ }
+ }
+ queryIndex--;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case I2C_CONFIG:
+ delayTime = (argv[0] + (argv[1] << 7));
+
+ if (argc > 1 && delayTime > 0) {
+ i2cReadDelayTime = delayTime;
+ }
+
+ if (!isI2CEnabled) {
+ enableI2CPins();
+ }
+
+ break;
+ case SERVO_CONFIG:
+ if (argc > 4) {
+ // these vars are here for clarity, they'll optimized away by the compiler
+ byte pin = argv[0];
+ int minPulse = argv[1] + (argv[2] << 7);
+ int maxPulse = argv[3] + (argv[4] << 7);
+
+ if (IS_PIN_DIGITAL(pin)) {
+ if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) {
+ detachServo(pin);
+ }
+ attachServo(pin, minPulse, maxPulse);
+ setPinModeCallback(pin, PIN_MODE_SERVO);
+ }
+ }
+ break;
+ case SAMPLING_INTERVAL:
+ if (argc > 1) {
+ samplingInterval = argv[0] + (argv[1] << 7);
+ if (samplingInterval < MINIMUM_SAMPLING_INTERVAL) {
+ samplingInterval = MINIMUM_SAMPLING_INTERVAL;
+ }
+ } else {
+ //Firmata.sendString("Not enough data");
+ }
+ break;
+ case EXTENDED_ANALOG:
+ if (argc > 1) {
+ int val = argv[1];
+ if (argc > 2) val |= (argv[2] << 7);
+ if (argc > 3) val |= (argv[3] << 14);
+ analogWriteCallback(argv[0], val);
+ }
+ break;
+ case CAPABILITY_QUERY:
+ Firmata.write(START_SYSEX);
+ Firmata.write(CAPABILITY_RESPONSE);
+ for (byte pin = 0; pin < TOTAL_PINS; pin++) {
+ if (IS_PIN_DIGITAL(pin)) {
+ Firmata.write((byte)INPUT);
+ Firmata.write(1);
+ Firmata.write((byte)PIN_MODE_PULLUP);
+ Firmata.write(1);
+ Firmata.write((byte)OUTPUT);
+ Firmata.write(1);
+ }
+ if (IS_PIN_ANALOG(pin)) {
+ Firmata.write(PIN_MODE_ANALOG);
+ Firmata.write(10); // 10 = 10-bit resolution
+ }
+ if (IS_PIN_PWM(pin)) {
+ Firmata.write(PIN_MODE_PWM);
+ Firmata.write(DEFAULT_PWM_RESOLUTION);
+ }
+ if (IS_PIN_DIGITAL(pin)) {
+ Firmata.write(PIN_MODE_SERVO);
+ Firmata.write(14);
+ }
+ if (IS_PIN_I2C(pin)) {
+ Firmata.write(PIN_MODE_I2C);
+ Firmata.write(1); // TODO: could assign a number to map to SCL or SDA
+ }
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.handleCapability(pin);
+#endif
+ Firmata.write(127);
+ }
+ Firmata.write(END_SYSEX);
+ break;
+ case PIN_STATE_QUERY:
+ if (argc > 0) {
+ byte pin = argv[0];
+ Firmata.write(START_SYSEX);
+ Firmata.write(PIN_STATE_RESPONSE);
+ Firmata.write(pin);
+ if (pin < TOTAL_PINS) {
+ Firmata.write(Firmata.getPinMode(pin));
+ Firmata.write((byte)Firmata.getPinState(pin) & 0x7F);
+ if (Firmata.getPinState(pin) & 0xFF80) Firmata.write((byte)(Firmata.getPinState(pin) >> 7) & 0x7F);
+ if (Firmata.getPinState(pin) & 0xC000) Firmata.write((byte)(Firmata.getPinState(pin) >> 14) & 0x7F);
+ }
+ Firmata.write(END_SYSEX);
+ }
+ break;
+ case ANALOG_MAPPING_QUERY:
+ Firmata.write(START_SYSEX);
+ Firmata.write(ANALOG_MAPPING_RESPONSE);
+ for (byte pin = 0; pin < TOTAL_PINS; pin++) {
+ Firmata.write(IS_PIN_ANALOG(pin) ? PIN_TO_ANALOG(pin) : 127);
+ }
+ Firmata.write(END_SYSEX);
+ break;
+
+ case SERIAL_MESSAGE:
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.handleSysex(command, argc, argv);
+#endif
+ break;
+ }
+}
+
+/*==============================================================================
+ * SETUP()
+ *============================================================================*/
+
+void systemResetCallback()
+{
+ isResetting = true;
+
+ // initialize a defalt state
+ // TODO: option to load config from EEPROM instead of default
+
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.reset();
+#endif
+
+ if (isI2CEnabled) {
+ disableI2CPins();
+ }
+
+ for (byte i = 0; i < TOTAL_PORTS; i++) {
+ reportPINs[i] = false; // by default, reporting off
+ portConfigInputs[i] = 0; // until activated
+ previousPINs[i] = 0;
+ }
+
+ for (byte i = 0; i < TOTAL_PINS; i++) {
+ // pins with analog capability default to analog input
+ // otherwise, pins default to digital output
+ if (IS_PIN_ANALOG(i)) {
+ // turns off pullup, configures everything
+ setPinModeCallback(i, PIN_MODE_ANALOG);
+ } else if (IS_PIN_DIGITAL(i)) {
+ // sets the output to 0, configures portConfigInputs
+ setPinModeCallback(i, OUTPUT);
+ }
+
+ servoPinMap[i] = 255;
+ }
+ // by default, do not report any analog inputs
+ analogInputsToReport = 0;
+
+ detachedServoCount = 0;
+ servoCount = 0;
+
+ /* send digital inputs to set the initial state on the host computer,
+ * since once in the loop(), this firmware will only send on change */
+ /*
+ TODO: this can never execute, since no pins default to digital input
+ but it will be needed when/if we support EEPROM stored config
+ for (byte i=0; i < TOTAL_PORTS; i++) {
+ outputPort(i, readPort(i, portConfigInputs[i]), true);
+ }
+ */
+ isResetting = false;
+}
+
+/*
+ * Called when a TCP connection is either connected or disconnected.
+ * TODO:
+ * - report connected or reconnected state to host (to be added to protocol)
+ * - report current state to host (to be added to protocol)
+ */
+void hostConnectionCallback(byte state)
+{
+ switch (state) {
+ case HOST_CONNECTION_CONNECTED:
+ DEBUG_PRINTLN( "TCP connection established" );
+ break;
+ case HOST_CONNECTION_DISCONNECTED:
+ DEBUG_PRINTLN( "TCP connection disconnected" );
+ break;
+ }
+}
+
+/*
+ * Print the status of the WiFi connection. This is the connection to the access point rather
+ * than the TCP connection.
+ */
+void printWifiStatus() {
+ if ( WiFi.status() != WL_CONNECTED )
+ {
+ DEBUG_PRINT( "WiFi connection failed. Status value: " );
+ DEBUG_PRINTLN( WiFi.status() );
+ }
+ else
+ {
+ // print the SSID of the network you're attached to:
+ DEBUG_PRINT( "SSID: " );
+ DEBUG_PRINTLN( WiFi.SSID() );
+
+ // print your WiFi shield's IP address:
+ DEBUG_PRINT( "IP Address: " );
+ IPAddress ip = WiFi.localIP();
+ DEBUG_PRINTLN( ip );
+
+ // print the received signal strength:
+ DEBUG_PRINT( "signal strength (RSSI): " );
+ long rssi = WiFi.RSSI();
+ DEBUG_PRINT( rssi );
+ DEBUG_PRINTLN( " dBm" );
+ }
+}
+
+/*
+ * StandardFirmataWiFi communicates with WiFi shields over SPI. Therefore all
+ * SPI pins must be set to IGNORE. Otherwise Firmata would break SPI communication.
+ * Additional pins may also need to be ignored depending on the particular board or
+ * shield in use.
+ */
+void ignorePins()
+{
+#ifdef IS_IGNORE_PIN
+ for (byte i = 0; i < TOTAL_PINS; i++) {
+ if (IS_IGNORE_PIN(i)) {
+ Firmata.setPinMode(i, PIN_MODE_IGNORE);
+ }
+ }
+#endif
+
+ //Set up controls for the Arduino WiFi Shield SS for the SD Card
+#ifdef ARDUINO_WIFI_SHIELD
+ // Arduino WiFi Shield has SD SS wired to D4
+ pinMode(PIN_TO_DIGITAL(4), OUTPUT); // switch off SD card bypassing Firmata
+ digitalWrite(PIN_TO_DIGITAL(4), HIGH); // SS is active low;
+
+#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
+ pinMode(PIN_TO_DIGITAL(53), OUTPUT); // configure hardware SS as output on MEGA
+#endif //defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
+
+#endif //ARDUINO_WIFI_SHIELD
+}
+
+void initTransport()
+{
+ // This statement will clarify how a connection is being made
+ DEBUG_PRINT( "StandardFirmataWiFi will attempt a WiFi connection " );
+#if defined(WIFI_101)
+ DEBUG_PRINTLN( "using the WiFi 101 library." );
+#elif defined(ARDUINO_WIFI_SHIELD)
+ DEBUG_PRINTLN( "using the legacy WiFi library." );
+#elif defined(ESP8266_WIFI)
+ DEBUG_PRINTLN( "using the ESP8266 WiFi library." );
+#elif defined(HUZZAH_WIFI)
+ DEBUG_PRINTLN( "using the HUZZAH WiFi library." );
+ //else should never happen here as error-checking in wifiConfig.h will catch this
+#endif //defined(WIFI_101)
+
+ // Configure WiFi IP Address
+#ifdef STATIC_IP_ADDRESS
+ DEBUG_PRINT( "Using static IP: " );
+ DEBUG_PRINTLN( local_ip );
+#if defined(ESP8266_WIFI) || (defined(SUBNET_MASK) && defined(GATEWAY_IP_ADDRESS))
+ stream.config( local_ip , gateway, subnet );
+#else
+ // you can also provide a static IP in the begin() functions, but this simplifies
+ // ifdef logic in this sketch due to support for all different encryption types.
+ stream.config( local_ip );
+#endif
+#else
+ DEBUG_PRINTLN( "IP will be requested from DHCP ..." );
+#endif
+
+ stream.attach(hostConnectionCallback);
+
+ // Configure WiFi security and initiate WiFi connection
+#if defined(WIFI_WEP_SECURITY)
+ DEBUG_PRINT( "Attempting to connect to WEP SSID: " );
+ DEBUG_PRINTLN(ssid);
+ stream.begin(ssid, wep_index, wep_key);
+#elif defined(WIFI_WPA_SECURITY)
+ DEBUG_PRINT( "Attempting to connect to WPA SSID: " );
+ DEBUG_PRINTLN(ssid);
+ stream.begin(ssid, wpa_passphrase);
+#else //OPEN network
+ DEBUG_PRINTLN( "Attempting to connect to open SSID: " );
+ DEBUG_PRINTLN(ssid);
+ stream.begin(ssid);
+#endif //defined(WIFI_WEP_SECURITY)
+ DEBUG_PRINTLN( "WiFi setup done" );
+
+ // Wait for connection to access point to be established.
+ while (WiFi.status() != WL_CONNECTED && ++connectionAttempts <= MAX_CONN_ATTEMPTS) {
+ delay(500);
+ DEBUG_PRINT(".");
+ }
+ printWifiStatus();
+}
+
+void initFirmata()
+{
+ Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
+ Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
+ Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
+ Firmata.attach(REPORT_ANALOG, reportAnalogCallback);
+ Firmata.attach(REPORT_DIGITAL, reportDigitalCallback);
+ Firmata.attach(SET_PIN_MODE, setPinModeCallback);
+ Firmata.attach(SET_DIGITAL_PIN_VALUE, setPinValueCallback);
+ Firmata.attach(START_SYSEX, sysexCallback);
+ Firmata.attach(SYSTEM_RESET, systemResetCallback);
+
+ ignorePins();
+
+ // Initialize Firmata to use the WiFi stream object as the transport.
+ Firmata.begin(stream);
+ systemResetCallback(); // reset to default config
+}
+
+void setup()
+{
+ DEBUG_BEGIN(9600);
+
+ initTransport();
+
+ initFirmata();
+}
+
+/*==============================================================================
+ * LOOP()
+ *============================================================================*/
+void loop()
+{
+ byte pin, analogPin;
+
+ /* DIGITALREAD - as fast as possible, check for changes and output them to the
+ * Stream buffer using Stream.write() */
+ checkDigitalInputs();
+
+ /* STREAMREAD - processing incoming messagse as soon as possible, while still
+ * checking digital inputs. */
+ while (Firmata.available()) {
+ Firmata.processInput();
+ }
+
+ // TODO - ensure that Stream buffer doesn't go over 60 bytes
+
+ currentMillis = millis();
+ if (currentMillis - previousMillis > samplingInterval) {
+ previousMillis += samplingInterval;
+ /* ANALOGREAD - do all analogReads() at the configured sampling interval */
+ for (pin = 0; pin < TOTAL_PINS; pin++) {
+ if (IS_PIN_ANALOG(pin) && Firmata.getPinMode(pin) == PIN_MODE_ANALOG) {
+ analogPin = PIN_TO_ANALOG(pin);
+ if (analogInputsToReport & (1 << analogPin)) {
+ Firmata.sendAnalog(analogPin, analogRead(analogPin));
+ }
+ }
+ }
+ // report i2c data for all device with read continuous mode enabled
+ if (queryIndex > -1) {
+ for (byte i = 0; i < queryIndex + 1; i++) {
+ readAndReportData(query[i].addr, query[i].reg, query[i].bytes, query[i].stopTX);
+ }
+ }
+ }
+
+#ifdef FIRMATA_SERIAL_FEATURE
+ serialFeature.update();
+#endif
+
+ stream.maintain();
+}
--- /dev/null
+/*==============================================================================
+ * WIFI CONFIGURATION
+ *
+ * You must configure your particular hardware. Follow the steps below.
+ *
+ * By default, StandardFirmataWiFi is configured as a TCP server, to configure
+ * as a TCP client, see STEP 2.
+ *============================================================================*/
+
+// STEP 1 [REQUIRED]
+// Uncomment / comment the appropriate set of includes for your hardware (OPTION A, B or C)
+// Arduino MKR1000 or ESP8266 are enabled by default if compiling for either of those boards.
+
+/*
+ * OPTION A: Configure for Arduino MKR1000 or Arduino WiFi Shield 101
+ *
+ * This will configure StandardFirmataWiFi to use the WiFi101 library, which works with the
+ * Arduino WiFi101 shield and devices that have the WiFi101 chip built in (such as the MKR1000).
+ * It is compatible with 802.11 B/G/N networks.
+ *
+ * If you are using the MKR1000 board, continue on to STEP 2. If you are using the WiFi 101 shield,
+ * follow the instructions below.
+ *
+ * To enable for the WiFi 101 shield, uncomment the #define WIFI_101 below and verify the
+ * #define ARDUINO_WIFI_SHIELD is commented out for OPTION B.
+ *
+ * IMPORTANT: You must have the WiFI 101 library installed. To easily install this library, open
+ * the library manager via: Arduino IDE Menus: Sketch > Include Library > Manage Libraries > filter
+ * search for "WiFi101" > Select the result and click 'install'
+ */
+//#define WIFI_101
+
+//do not modify the following 11 lines
+#if defined(ARDUINO_SAMD_MKR1000) && !defined(WIFI_101)
+// automatically include if compiling for MRK1000
+#define WIFI_101
+#endif
+#ifdef WIFI_101
+#include <WiFi101.h>
+#include "utility/WiFiClientStream.h"
+#include "utility/WiFiServerStream.h"
+ #define WIFI_LIB_INCLUDED
+#endif
+
+/*
+ * OPTION B: Configure for legacy Arduino WiFi shield
+ *
+ * This will configure StandardFirmataWiFi to use the original WiFi library (deprecated) provided
+ * with the Arduino IDE. It is supported by the Arduino WiFi shield (a discontinued product) and
+ * is compatible with 802.11 B/G networks.
+ *
+ * To configure StandardFirmataWiFi to use the legacy Arduino WiFi shield
+ * leave the #define below uncommented and ensure #define WIFI_101 is commented out for OPTION A.
+ */
+//#define ARDUINO_WIFI_SHIELD
+
+//do not modify the following 10 lines
+#ifdef ARDUINO_WIFI_SHIELD
+#include <WiFi.h>
+#include "utility/WiFiClientStream.h"
+#include "utility/WiFiServerStream.h"
+ #ifdef WIFI_LIB_INCLUDED
+ #define MULTIPLE_WIFI_LIB_INCLUDES
+ #else
+ #define WIFI_LIB_INCLUDED
+ #endif
+#endif
+
+/*
+ * OPTION C: Configure for ESP8266
+ *
+ * This will configure StandardFirmataWiFi to use the ESP8266WiFi library for boards
+ * with an ESP8266 chip. It is compatible with 802.11 B/G/N networks.
+ *
+ * The appropriate libraries are included automatically when compiling for the ESP8266 so
+ * continue on to STEP 2.
+ *
+ * IMPORTANT: You must have the esp8266 board support installed. To easily install this board see
+ * the instructions here: https://github.com/esp8266/Arduino#installing-with-boards-manager.
+ */
+//do not modify the following 14 lines
+#ifdef ESP8266
+// automatically include if compiling for ESP8266
+#define ESP8266_WIFI
+#endif
+#ifdef ESP8266_WIFI
+#include <ESP8266WiFi.h>
+#include "utility/WiFiClientStream.h"
+#include "utility/WiFiServerStream.h"
+ #ifdef WIFI_LIB_INCLUDED
+ #define MULTIPLE_WIFI_LIB_INCLUDES
+ #else
+ #define WIFI_LIB_INCLUDED
+ #endif
+#endif
+
+/*
+ * OPTION D: Configure for HUZZAH
+ *
+ * HUZZAH with CC3000 is not yet supported, this will be added in a later revision to
+ * StandardFirmataWiFi.
+ * For HUZZAH with ESP8266 use ESP8266_WIFI.
+ */
+
+//------------------------------
+// TODO
+//------------------------------
+//#define HUZZAH_WIFI
+
+
+// STEP 2 [OPTIONAL for all boards and shields]
+// If you want to setup you board as a TCP client, uncomment the following define and replace
+// the IP address with the IP address of your server.
+//#define SERVER_IP 10, 0, 0, 15
+
+
+// STEP 3 [REQUIRED for all boards and shields]
+// replace this with your wireless network SSID
+char ssid[] = "your_network_name";
+
+
+// STEP 4 [OPTIONAL for all boards and shields]
+// If you want to use a static IP (v4) address, uncomment the line below. You can also change the IP.
+// If the first line is commented out, the WiFi shield will attempt to get an IP from the DHCP server.
+// If you are using a static IP with the ESP8266 then you must also uncomment the SUBNET and GATEWAY.
+//#define STATIC_IP_ADDRESS 192,168,1,113
+//#define SUBNET_MASK 255,255,255,0 // REQUIRED for ESP8266_WIFI, optional for others
+//#define GATEWAY_IP_ADDRESS 0,0,0,0 // REQUIRED for ESP8266_WIFI, optional for others
+
+
+// STEP 5 [REQUIRED for all boards and shields]
+// define your port number here, you will need this to open a TCP connection to your Arduino
+#define SERVER_PORT 3030
+
+
+// STEP 6 [REQUIRED for all boards and shields]
+// determine your network security type (OPTION A, B, or C). Option A is the most common, and the
+// default.
+
+/*
+ * OPTION A: WPA / WPA2
+ *
+ * WPA is the most common network security type. A passphrase is required to connect to this type.
+ *
+ * To enable, leave #define WIFI_WPA_SECURITY uncommented below, set your wpa_passphrase value
+ * appropriately, and do not uncomment the #define values under options B and C
+ */
+#define WIFI_WPA_SECURITY
+
+#ifdef WIFI_WPA_SECURITY
+char wpa_passphrase[] = "your_wpa_passphrase";
+#endif //WIFI_WPA_SECURITY
+
+
+/*
+ * OPTION B: WEP
+ *
+ * WEP is a less common (and regarded as less safe) security type. A WEP key and its associated
+ * index are required to connect to this type.
+ *
+ * To enable, Uncomment the #define below, set your wep_index and wep_key values appropriately,
+ * and verify the #define values under options A and C are commented out.
+ */
+//#define WIFI_WEP_SECURITY
+
+#ifdef WIFI_WEP_SECURITY
+//The wep_index below is a zero-indexed value.
+//Valid indices are [0-3], even if your router/gateway numbers your keys [1-4].
+byte wep_index = 0;
+char wep_key[] = "your_wep_key";
+#endif //WIFI_WEP_SECURITY
+
+
+/*
+ * OPTION C: Open network (no security)
+ *
+ * Open networks have no security, can be connected to by any device that knows the ssid, and are
+ * unsafe.
+ *
+ * To enable, uncomment #define WIFI_NO_SECURITY below and verify the #define values
+ * under options A and B are commented out.
+ */
+//#define WIFI_NO_SECURITY
+
+/*==============================================================================
+ * CONFIGURATION ERROR CHECK (don't change anything here)
+ *============================================================================*/
+
+#ifdef MULTIPLE_WIFI_LIB_INCLUDES
+#error "you may not define more than one wifi device type in wifiConfig.h."
+#endif
+
+#ifndef WIFI_LIB_INCLUDED
+#error "you must define a wifi device type in wifiConfig.h."
+#endif
+
+#if ((defined(WIFI_NO_SECURITY) && (defined(WIFI_WEP_SECURITY) || defined(WIFI_WPA_SECURITY))) || (defined(WIFI_WEP_SECURITY) && defined(WIFI_WPA_SECURITY)))
+#error "you may not define more than one security type at the same time in wifiConfig.h."
+#endif //WIFI_* security define check
+
+#if !(defined(WIFI_NO_SECURITY) || defined(WIFI_WEP_SECURITY) || defined(WIFI_WPA_SECURITY))
+#error "you must define a wifi security type in wifiConfig.h."
+#endif //WIFI_* security define check
+
+#if (defined(ESP8266_WIFI) && !(defined(WIFI_NO_SECURITY) || (defined(WIFI_WPA_SECURITY))))
+#error "you must choose between WIFI_NO_SECURITY and WIFI_WPA_SECURITY"
+#endif
+
+/*==============================================================================
+ * WIFI STREAM (don't change anything here)
+ *============================================================================*/
+
+#ifdef SERVER_IP
+ WiFiClientStream stream(IPAddress(SERVER_IP), SERVER_PORT);
+#else
+ WiFiServerStream stream(SERVER_PORT);
+#endif
+
+/*==============================================================================
+ * PIN IGNORE MACROS (don't change anything here)
+ *============================================================================*/
+
+#if defined(WIFI_101) && !defined(ARDUINO_SAMD_MKR1000)
+// ignore SPI pins, pin 5 (reset WiFi101 shield), pin 7 (WiFi handshake) and pin 10 (WiFi SS)
+// also don't ignore SS pin if it's not pin 10. Not needed for Arduino MKR1000.
+#define IS_IGNORE_PIN(p) ((p) == 10 || (IS_PIN_SPI(p) && (p) != SS) || (p) == 5 || (p) == 7)
+
+#elif defined(ARDUINO_WIFI_SHIELD) && defined(__AVR_ATmega32U4__)
+// ignore SPI pins, pin 4 (SS for SD-Card on WiFi-shield), pin 7 (WiFi handshake) and pin 10 (WiFi SS)
+// On Leonardo, pin 24 maps to D4 and pin 28 maps to D10
+#define IS_IGNORE_PIN(p) ((IS_PIN_SPI(p) || (p) == 4) || (p) == 7 || (p) == 10 || (p) == 24 || (p) == 28)
+
+#elif defined(ARDUINO_WIFI_SHIELD)
+// ignore SPI pins, pin 4 (SS for SD-Card on WiFi-shield), pin 7 (WiFi handshake) and pin 10 (WiFi SS)
+#define IS_IGNORE_PIN(p) ((IS_PIN_SPI(p) || (p) == 4) || (p) == 7 || (p) == 10)
+
+#elif defined(ESP8266_WIFI) && defined(SERIAL_DEBUG)
+#define IS_IGNORE_PIN(p) ((p) == 1)
+
+#endif
--- /dev/null
+FIRMATA 2.5.7 - Aug 19, 2017
+
+[core library]
+* Added support for Adafruit nrf52 boards (hathach)
+* Added TCP server option to StandardFirmataEthernet (MJPees)
+* Added support for STM32-based boards (fpistm)
+* Added support for MKRFox1200 (sandeepmistry)
+
+[StandardFirmata & variants]
+* Fixed I2C config parameter interpretation (zfields)
+* Improve debug output in StandardFirmataEthernet
+
+FIRMATA 2.5.6 - Mar 18, 2017
+
+[core library]
+* Fixed string encoder/decoder bug that also affected I2C (Zak Fields)
+* Added support for Arduino Primo (chiararuggeri)
+* Added unit tests for Firmata string message encoding/decoding
+
+FIRMATA 2.5.5 - Mar 6, 2017
+
+[core library]
+* Updated BLEStream for compatibility with CurieBLE v2 (Sandeep Mistry)
+* Added support for MKRZero (Sandeep Mistry)
+
+This update also includes a number of changes from an ongoing refactor by
+Zak Fields of the Firmata core. These changes don't impact user facing sketches,
+they are all internal only. Changes include:
+
+* Split out parser logic into new lib free of Arduino-specific dependencies.
+* Add new class to support cross platform marshalling of Firmata procedure calls.
+* Split out core constants to separate file.
+* Split out core defines to separate file.
+* Added firmata namespace to core library classes.
+
+FIRMATA 2.5.4 - Oct 23, 2016
+
+[core library]
+* Added Teensy 3.5 and 3.6 to Boards.h
+* Assign blinkVersionDisabled in constructor to fix compiler issue in Arduino 1.0.6
+
+[StandardFirmata & variants]
+* Only disable PWM when setting pinMode to OUTPUT if pinMode was previously PWM
+* Forward declare some functions to fix compiler issues with older IDE versions
+
+FIRMATA 2.5.3 - Jun 18, 2016
+
+[core library]
+* Added ESP8266 support (Jens B. & Jacob Rosenthal)
+* Added host connection callback (Jens B.)
+* Added Wi-Fi TCP client (Jens B.)
+* Added BLE transport (BLEStream based on BLESerial by Volta Molda)
+* Fixed Arduino Galileo and Edison compile issues
+
+[StandardFirmata & variants]
+* Added StandardFirmataBLE (for use with Arduino 101)
+* Added ability to choose between Wi-Fi TCP client or server (Jens B.)
+* Various updates to StandardFirmataWiFi (Jens B.)
+* Increased I2C RX data buffer from 32 to 64 bytes (Rick Waldron)
+* Removed StandardFirmataEthernetPlus
+* Made StandardFirmataEtherent configurable (to optionally add Plus functionality)
+* Improved configuration instructions for StandardFirmataEthernet and StandardFirmataWiFi
+
+FIRMATA 2.5.2 - Feb 15, 2016
+
+[core library]
+* Added Wi-Fi transport (Jesse Frush)
+* Added support for Arduino MKR1000 (Jesse Frush)
+* Moved Serial feature to own class SerialFirmata
+* Moved pin config and pin state handling to Firmata.cpp
+* Added new method disableBlinkVersion to provide a way to optionally bypass startup blink sequence
+
+[StandardFirmata & variants]
+* Added StandardFirmataWiFi (Jesse Frush)
+* Added ethernetConfig.h for StandardFirmataEthernet and StandardFirmtaEthernetPlus
+* Removed serialUtils.h and using SerialFirmata class instead for Serial feature
+
+FIRMATA 2.5.1 - Dec 26, 2015
+
+[core library]
+* Added support for Arduino 101
+* Make VERSION_BLINK_PIN optional
+* Separate protocol version from firmware version.
+ Use FIRMATA_PROTOCOL_VERSION_[MAJOR/MINOR/BUGFIX] for protocol and use
+ FIRMATA_FIRMWARE_VERSION_[MAJOR/MINOR/BUGFIX] for firmware (library version).
+
+[StandardFirmata & variants]
+* Added ability to auto-restart I2C transmission by setting bit 6 of byte 3
+ of the I2C_REQUEST message.
+
+FIRMATA 2.5.0 - Nov 7, 2015
+
+[core library]
+* Added Serial feature for interfacing with serial devices via hardware
+ or software serial. See github.com/firmata/protocol/serial.md for details
+* Added ability to set the value of a pin by sending a single value instead
+ of a port value. See 'set digital pin value' in github.com/firmata/protocol/protocol.md
+ for details
+* Added support for Arduino Zero board
+* Added support for Teensy LC board (copied from Teensy Firmata lib)
+* Added support for Pinoccio Scout board (Pawel Szymczykowski)
+* Lowered minimun sampling interval from 10 to 1 millisecond
+* Added new pin mode (PIN_MODE_PULLUP) for setting the INPUT_PULLUP pin mode
+* Changed pin mode defines to safer names (old names still included but
+ deprecated) - see Firmata.h
+
+[StandardFirmata & variants]
+* Created new StandardFirmataPlus that implements the Serial feature
+ Note: The new Serial features is only implemented in the "Plus" versions of
+ StandardFirmata.
+* Created new StandardFirmataEthernetPlus that implements the Serial feature
+* Fixed issue where StandardFirmata was not compiling for Intel Galileo boards
+* Moved StandardFirmataYun to its own repo (github.com/firmata/StandardFirmataYun)
+
+FIRMATA 2.4.4 - Aug 9, 2015
+
+[core library]
+* Added support for chipKIT boards (Brian Schmalz, Rick Anderson and Keith Vogel)
+* Added support for ATmega328 boards (previously only ATmega328p was supported)
+
+[StandardFirmata]
+* Added StandardFirmataChipKIT for ChipKIT boards (Brian Schmalz, Rick Anderson and Keith Vogel)
+* Ensure Serial is ready on Leonardo and other ATMega32u4-based boards
+
+FIRMATA 2.4.3 - Apr 11, 2015
+
+[core library]
+* Added debug macros (utility/firmataDebug.h)
+* Added Norbert Truchsess' EthernetClientStream lib from the configurable branch
+
+[examples]
+* Added StandardFirmataEthernet to enable Firmata over Ethernet
+* Minor updates to StandardFirmata and StandardFirmataYun
+
+FIRMATA 2.4.2 - Mar 16, 2015
+
+[core library]
+* Add support for Teesy 3.1 (Olivier Louvignes)
+
+FIRMATA 2.4.1 - Feb 7, 2015
+
+[core library]
+* Fixed off-by-one bug in setFirmwareNameAndVersion (Brian Schmalz)
+
+[StandardFirmata]
+* Prevent analog values from being reported during system reset
+
+FIRMATA 2.4.0 - Dec 21, 2014
+
+Changes from 2.3.6 to 2.4 that may impact existing Firmata client implementations:
+
+* When sending a string from the client application to the board (STRING_DATA) a
+static buffer is now used for the incoming string in place of a dynamically allocated
+block of memory (see Firmata.cpp lines 181 - 205). In Firmata 2.3.6 and older,
+the dynamically allocated block was never freed, causing a memory leak. If your
+client library had freed this memory in the string callback method, that code
+will break in Firmata 2.4. If the string data needs to persist beyond the string
+callback, it should be copied within the string callback.
+
+* As of Firmata 2.4, when digital port reporting or analog pin reporting is enabled,
+the value of the port (digital) or pin (analog) is immediately sent back to the client
+application. This will likely not have a negative impact on existing client
+implementations, but may be unexpected. This feature was added to better support
+non-serial streams (such as Ethernet, Wi-Fi, Bluetooth, etc) that may lose
+connectivity and need a quick way to get the current state of the pins upon
+reestablishing a connection.
+
+[core library]
+* Changed sendValueAsTwo7bitBytes, startSysex and endSysex from private to
+ public methods.
+* Added Intel Galileo to Boards.h
+* Renamed FirmataSerial to FirmataStream
+* Updated to latest Arduino library format
+* writePort function in Boards.h now returns 1 (to suppress compiler warning)
+* Updated syntax highlighting (keywords.txt)
+* Fixed IS_PIN_SPI ifndef condition in boards.h
+* Added constants to Firmata.h to reserve configurable firmata features
+* Fixed issue where firmwareName was not reported correctly in Windows
+* Ensure incoming String via STRING_DATA command is null-terminated
+* Fixed memory leak when receiving String via STRING_DATA command
+ (note this change may break existing code if you were manually deallocating
+ the incoming string in your string callback function. See code for details)
+* Added ability for user to specify a filename when calling setFirmwareNameAndVersion
+* Increased input data buffer size from 32 to 64 bytes
+
+[StandardFirmata]
+* Updated I2C_READ_CONTINUOUSLY to work with or without slaveRegister (Rick Waldron)
+* Added Yun variant of StandardFirmata
+* When a digital port is enabled, its value is now immediately sent to the client
+* When an analog pin is enabled, its value is now immediately sent to the client
+* Changed the way servo pins are mapped to enable use of servos on
+ a wider range of pins, including analog pins.
+* Fixed management of unexpected sized I2C replies (Nahuel Greco)
+* Fixed a bug when removing a monitored device with I2C_STOP_Reading (Nahuel Greco)
+* Fixed conditional expression in I2C_STOP_READING case
+* Changed samplingInterval from type int to type unsigned int
+* Shortened error message strings to save a few bytes
+
+[examples]
+* Updated FirmataServo example to use new pin mapping technique
+* Removed makefiles from examples (because they were not being updated)
+* Updated all examples to set current firmware version
+
+FIRMATA 2.3.6 - Jun 18, 2013 (Version included with Arduino core libraries)
+
+[core library]
+* Fixed bug introduced in 2.3.5 that broke ability to use Ethernet.
+
+FIRMATA 2.3.5 - May 21, 2013
+
+[core library]
+* Added Arduino Due to Boards.h
+* Added Teensy 3.0 to Boards.h
+* Updated unit tests to use ArduinoUnit v2.0
+* Renamed pin13strobe to strobeBlinkPin
+* Removed blinkVersion method from begin method for non-serial streams
+* Fixed memory leak in setting firmware version (Matthew Murdoch)
+* Added unit tests for a few core functions (Matthew Murdoch)
+* Added IS_PIN_SPI macro to all board definitions in Board.h (Norbert Truchsess)
+
+FIRMATA 2.3.4 - Feb 11, 2013
+
+[core library]
+* Fixed Stream implementation so Firmata can be used with Streams other than
+ Serial (Norbert Truchsess)
+
+FIRMATA 2.3.3 - Oct 6, 2012
+
+[core library]
+* Added write method to expose FirmataSerial.write
+* Added Arduino Leonardo to Boards.h
+
+[StandardFirmata]
+* Changed all instances of Serial.write to Firmata.write
+* Fixed delayMicroseconds(0) bug in readAndReportData
+
+FIRMATA 2.3.0 - 2.3.2
+
+* Removed angle from servo config
+* Changed file extensions from .pde to .ino
+* Added MEGA2560 to Boards.h
+* Added I2C pins to Boards.h
+* Modified examples to be compatible with Arduino 0022 and 1.0 or greater
+* Removed I2CFirmata example
+* Changes to StandardFirmata
+ * Added I2C support
+ * Added system reset message to reset all pins to default config on sysex reset
+
+FIRMATA 2.2 (changes prior to Firmata 2.3.0 were not well documented)
+
+* changes undocumented
+
+FIRMATA 2.1
+
+* added support for changing the sampling interval
+* added Servo support
+
+FIRMATA 2.0
+
+* changed to 8-bit port-based digital messages to mirror ports from previous 14-bit ports modeled after the standard Arduino board.
+* switched order of version message so major version is reported first
+
+FIRMATA 1.0
+
+* switched to MIDI-compatible packet format (though the message interpretation differs)
--- /dev/null
+#######################################
+# Syntax Coloring Map For Firmata
+#######################################
+
+#######################################
+# Datatypes (KEYWORD1)
+#######################################
+
+Firmata KEYWORD1 Firmata
+callbackFunction KEYWORD1 callbackFunction
+systemResetCallbackFunction KEYWORD1 systemResetCallbackFunction
+stringCallbackFunction KEYWORD1 stringCallbackFunction
+sysexCallbackFunction KEYWORD1 sysexCallbackFunction
+
+#######################################
+# Methods and Functions (KEYWORD2)
+#######################################
+
+begin KEYWORD2
+printVersion KEYWORD2
+blinkVersion KEYWORD2
+printFirmwareVersion KEYWORD2
+setFirmwareVersion KEYWORD2
+setFirmwareNameAndVersion KEYWORD2
+available KEYWORD2
+processInput KEYWORD2
+isParsingMessage KEYWORD2
+parse KEYWORD2
+sendAnalog KEYWORD2
+sendDigital KEYWORD2
+sendDigitalPort KEYWORD2
+sendString KEYWORD2
+sendSysex KEYWORD2
+getPinMode KEYWORD2
+setPinMode KEYWORD2
+getPinState KEYWORD2
+setPinState KEYWORD2
+attach KEYWORD2
+detach KEYWORD2
+write KEYWORD2
+sendValueAsTwo7bitBytes KEYWORD2
+startSysex KEYWORD2
+endSysex KEYWORD2
+writePort KEYWORD2
+readPort KEYWORD2
+disableBlinkVersion KEYWORD2
+
+
+#######################################
+# Constants (LITERAL1)
+#######################################
+
+FIRMATA_MAJOR_VERSION LITERAL1
+FIRMATA_MINOR_VERSION LITERAL1
+FIRMATA_BUGFIX_VERSION LITERAL1
+
+MAX_DATA_BYTES LITERAL1
+
+DIGITAL_MESSAGE LITERAL1
+ANALOG_MESSAGE LITERAL1
+REPORT_ANALOG LITERAL1
+REPORT_DIGITAL LITERAL1
+REPORT_VERSION LITERAL1
+SET_PIN_MODE LITERAL1
+SET_DIGITAL_PIN_VALUE LITERAL1
+SYSTEM_RESET LITERAL1
+START_SYSEX LITERAL1
+END_SYSEX LITERAL1
+REPORT_FIRMWARE LITERAL1
+STRING_DATA LITERAL1
+
+PIN_MODE_ANALOG LITERAL1
+PIN_MODE_PWM LITERAL1
+PIN_MODE_SERVO LITERAL1
+PIN_MODE_SHIFT LITERAL1
+PIN_MODE_I2C LITERAL1
+PIN_MODE_ONEWIRE LITERAL1
+PIN_MODE_STEPPER LITERAL1
+PIN_MODE_ENCODER LITERAL1
+PIN_MODE_SERIAL LITERAL1
+PIN_MODE_PULLUP LITERAL1
+PIN_MODE_IGNORE LITERAL1
+
+TOTAL_PINS LITERAL1
+TOTAL_ANALOG_PINS LITERAL1
+TOTAL_DIGITAL_PINS LITERAL1
+TOTAL_PIN_MODES LITERAL1
+TOTAL_PORTS LITERAL1
+ANALOG_PORT LITERAL1
+MAX_SERVOS LITERAL1
--- /dev/null
+name=Firmata\r
+version=2.5.7\r
+author=Firmata Developers\r
+maintainer=https://github.com/firmata/arduino\r
+sentence=Enables the communication with computer apps using a standard serial protocol. For all Arduino/Genuino boards.\r
+paragraph=The Firmata library implements the Firmata protocol for communicating with software on the host computer. This allows you to write custom firmware without having to create your own protocol and objects for the programming environment that you are using.\r
+category=Device Control\r
+url=https://github.com/firmata/arduino\r
+architectures=*\r
--- /dev/null
+# Firmata
+
+[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/firmata/arduino?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
+Firmata is a protocol for communicating with microcontrollers from software on a host computer. The [protocol](https://github.com/firmata/protocol) can be implemented in firmware on any microcontroller architecture as well as software on any host computer software package. The Arduino repository described here is a Firmata library for Arduino and Arduino-compatible devices. If you would like to contribute to Firmata, please see the [Contributing](#contributing) section below.
+
+# Contents
+
+- [Usage](#usage)
+- [Firmata Client Libraries](#firmata-client-libraries)
+- [Updating Firmata in the Arduino IDE - Arduino 1.6.4 and higher](#updating-firmata-in-the-arduino-ide---arduino-164-and-higher)
+- [Cloning Firmata](#cloning-firmata)
+- [Updating Firmata in the Arduino IDE - older versions (<= 1.6.3 or 1.0.x)](#updating-firmata-in-the-arduino-ide---older-versions--163-or-10x)
+ - [Mac OSX:](#mac-osx)
+ - [Windows](#windows)
+ - [Linux](#linux)
+- [Using the Source code rather than release archive (only for versions older than Arduino 1.6.3)](#using-the-source-code-rather-than-release-archive-only-for-versions-older-than-arduino-163)
+- [Contributing](#contributing)
+
+## Usage
+
+There are two main models of usage of Firmata. In one model, the author of the Arduino sketch uses the various methods provided by the Firmata library to selectively send and receive data between the Arduino device and the software running on the host computer. For example, a user can send analog data to the host using ``` Firmata.sendAnalog(analogPin, analogRead(analogPin)) ``` or send data packed in a string using ``` Firmata.sendString(stringToSend) ```. See File -> Examples -> Firmata -> AnalogFirmata & EchoString respectively for examples.
+
+The second and more common model is to load a general purpose sketch called StandardFirmata (or one of the variants such as StandardFirmataPlus or StandardFirmataEthernet depending on your needs) on the Arduino board and then use the host computer exclusively to interact with the Arduino board. StandardFirmata is located in the Arduino IDE in File -> Examples -> Firmata.
+
+## Firmata Client Libraries
+Most of the time you will be interacting with Arduino with a client library on the host computers. Several Firmata client libraries have been implemented in a variety of popular programming languages:
+
+* processing
+ * [https://github.com/firmata/processing](https://github.com/firmata/processing)
+ * [http://funnel.cc](http://funnel.cc)
+* python
+ * [https://github.com/MrYsLab/pymata-aio](https://github.com/MrYsLab/pymata-aio)
+ * [https://github.com/MrYsLab/PyMata]([https://github.com/MrYsLab/PyMata)
+ * [https://github.com/tino/pyFirmata](https://github.com/tino/pyFirmata)
+ * [https://github.com/lupeke/python-firmata](https://github.com/lupeke/python-firmata)
+ * [https://github.com/firmata/pyduino](https://github.com/firmata/pyduino)
+* perl
+ * [https://github.com/ntruchsess/perl-firmata](https://github.com/ntruchsess/perl-firmata)
+ * [https://github.com/rcaputo/rx-firmata](https://github.com/rcaputo/rx-firmata)
+* ruby
+ * [https://github.com/hardbap/firmata](https://github.com/hardbap/firmata)
+ * [https://github.com/PlasticLizard/rufinol](https://github.com/PlasticLizard/rufinol)
+ * [http://funnel.cc](http://funnel.cc)
+* clojure
+ * [https://github.com/nakkaya/clodiuno](https://github.com/nakkaya/clodiuno)
+ * [https://github.com/peterschwarz/clj-firmata](https://github.com/peterschwarz/clj-firmata)
+* javascript
+ * [https://github.com/jgautier/firmata](https://github.com/jgautier/firmata)
+ * [https://github.com/rwldrn/johnny-five](https://github.com/rwldrn/johnny-five)
+ * [http://breakoutjs.com](http://breakoutjs.com)
+* java
+ * [https://github.com/kurbatov/firmata4j](https://github.com/kurbatov/firmata4j)
+ * [https://github.com/4ntoine/Firmata](https://github.com/4ntoine/Firmata)
+ * [https://github.com/reapzor/FiloFirmata](https://github.com/reapzor/FiloFirmata)
+* .NET
+ * [https://github.com/SolidSoils/Arduino](https://github.com/SolidSoils/Arduino)
+ * [http://www.acraigie.com/programming/firmatavb/default.html](http://www.acraigie.com/programming/firmatavb/default.html)
+* Flash/AS3
+ * [http://funnel.cc](http://funnel.cc)
+ * [http://code.google.com/p/as3glue/](http://code.google.com/p/as3glue/)
+* PHP
+ * [https://github.com/ThomasWeinert/carica-firmata]()
+ * [https://github.com/oasynnoum/phpmake_firmata](https://github.com/oasynnoum/phpmake_firmata)
+* Haskell
+ * [http://hackage.haskell.org/package/hArduino](http://hackage.haskell.org/package/hArduino)
+* iOS
+ * [https://github.com/jacobrosenthal/iosfirmata](https://github.com/jacobrosenthal/iosfirmata)
+* Dart
+ * [https://github.com/nfrancois/firmata](https://github.com/nfrancois/firmata)
+* Max/MSP
+ * [http://www.maxuino.org/](http://www.maxuino.org/)
+* Elixir
+ * [https://github.com/kfatehi/firmata](https://github.com/kfatehi/firmata)
+* Modelica
+ * [https://www.wolfram.com/system-modeler/libraries/model-plug/](https://www.wolfram.com/system-modeler/libraries/model-plug/)
+* Go
+ * [https://github.com/kraman/go-firmata](https://github.com/kraman/go-firmata)
+* vvvv
+ * [https://vvvv.org/blog/arduino-second-service](https://vvvv.org/blog/arduino-second-service)
+* openFrameworks
+ * [http://openframeworks.cc/documentation/communication/ofArduino/](http://openframeworks.cc/documentation/communication/ofArduino/)
+* Rust
+ * [https://github.com/zankich/rust-firmata](https://github.com/zankich/rust-firmata)
+
+Note: The above libraries may support various versions of the Firmata protocol and therefore may not support all features of the latest Firmata spec nor all Arduino and Arduino-compatible boards. Refer to the respective projects for details.
+
+## Updating Firmata in the Arduino IDE - Arduino 1.6.4 and higher
+
+If you want to update to the latest stable version:
+
+1. Open the Arduino IDE and navigate to: `Sketch > Include Library > Manage Libraries`
+2. Filter by "Firmata" and click on the "Firmata by Firmata Developers" item in the list of results.
+3. Click the `Select version` dropdown and select the most recent version (note you can also install previous versions)
+4. Click `Install`.
+
+### Cloning Firmata
+
+If you are contributing to Firmata or otherwise need a version newer than the latest tagged release, you can clone Firmata directly to your Arduino/libraries/ directory (where 3rd party libraries are installed). This only works for Arduino 1.6.4 and higher, for older versions you need to clone into the Arduino application directory (see section below titled "Using the Source code rather than release archive"). Be sure to change the name to Firmata as follows:
+
+```bash
+$ git clone git@github.com:firmata/arduino.git ~/Documents/Arduino/libraries/Firmata
+```
+
+*Update path above if you're using Windows or Linux or changed the default Arduino directory on OS X*
+
+
+## Updating Firmata in the Arduino IDE - older versions (<= 1.6.3 or 1.0.x)
+
+Download the latest [release](https://github.com/firmata/arduino/releases/tag/2.5.7) (for Arduino 1.0.x or Arduino 1.5.6 or higher) and replace the existing Firmata folder in your Arduino application. See the instructions below for your platform.
+
+*Note that Arduino 1.5.0 - 1.5.5 are not supported. Please use Arduino 1.5.6 or higher (or Arduino 1.0.5 or 1.0.6).*
+
+### Mac OSX:
+
+The Firmata library is contained within the Arduino package.
+
+1. Navigate to the Arduino application
+2. Right click on the application icon and select `Show Package Contents`
+3. Navigate to: `/Contents/Resources/Java/libraries/` and replace the existing
+`Firmata` folder with latest [Firmata release](https://github.com/firmata/arduino/releases/tag/2.5.7) (note there is a different download
+for Arduino 1.0.x vs 1.6.x)
+4. Restart the Arduino application and the latest version of Firmata will be available.
+
+*If you are using the Java 7 version of Arduino 1.5.7 or higher, the file path
+will differ slightly: `Contents/Java/libraries/Firmata` (no Resources directory).*
+
+### Windows:
+
+1. Navigate to `c:/Program\ Files/arduino-1.x/libraries/` and replace the existing
+`Firmata` folder with the latest [Firmata release](https://github.com/firmata/arduino/releases/tag/2.5.7) (note there is a different download
+for Arduino 1.0.x vs 1.6.x).
+2. Restart the Arduino application and the latest version of Firmata will be available.
+
+*Update the path and Arduino version as necessary*
+
+### Linux:
+
+1. Navigate to `~/arduino-1.x/libraries/` and replace the existing
+`Firmata` folder with the latest [Firmata release](https://github.com/firmata/arduino/releases/tag/2.5.7) (note there is a different download
+for Arduino 1.0.x vs 1.6.x).
+2. Restart the Arduino application and the latest version of Firmata will be available.
+
+*Update the path and Arduino version as necessary*
+
+### Using the Source code rather than release archive (only for versions older than Arduino 1.6.3)
+
+*It is recommended you update to Arduino 1.6.4 or higher if possible, that way you can clone directly into the external Arduino/libraries/ directory which persists between Arduino application updates. Otherwise you will need to move your clone each time you update to a newer version of the Arduino IDE.*
+
+If you're stuck with an older version of the IDE, then follow these keep reading otherwise jump up to the "Cloning Firmata section above".
+
+Clone this repo directly into the core Arduino application libraries directory. If you are using
+Arduino 1.5.x or <= 1.6.3, the repo directory structure will not match the Arduino
+library format, however it should still compile as long as you are using Arduino 1.5.7
+or higher.
+
+You will first need to remove the existing Firmata library, then clone firmata/arduino
+into an empty Firmata directory:
+
+```bash
+$ rm -r /Applications/Arduino.app/Contents/Resources/Java/libraries/Firmata
+$ git clone git@github.com:firmata/arduino.git /Applications/Arduino.app/Contents/Resources/Java/libraries/Firmata
+```
+
+*Update paths if you're using Windows or Linux*
+
+To generate properly formatted versions of Firmata (for Arduino 1.0.x and Arduino 1.6.x), run the
+`release.sh` script.
+
+## Contributing
+
+If you discover a bug or would like to propose a new feature, please open a new [issue](https://github.com/firmata/arduino/issues?sort=created&state=open). Due to the limited memory of standard Arduino boards we cannot add every requested feature to StandardFirmata. Requests to add new features to StandardFirmata will be evaluated by the Firmata developers. However it is still possible to add new features to other Firmata implementations (Firmata is a protocol whereas StandardFirmata is just one of many possible implementations).
+
+To contribute, fork this repository and create a new topic branch for the bug, feature or other existing issue you are addressing. Submit the pull request against the *master* branch.
+
+If you would like to contribute but don't have a specific bugfix or new feature to contribute, you can take on an existing issue, see issues labeled "pull-request-encouraged". Add a comment to the issue to express your intent to begin work and/or to get any additional information about the issue.
+
+You must thoroughly test your contributed code. In your pull request, describe tests performed to ensure that no existing code is broken and that any changes maintain backwards compatibility with the existing api. Test on multiple Arduino board variants if possible. We hope to enable some form of automated (or at least semi-automated) testing in the future, but for now any tests will need to be executed manually by the contributor and reviewers.
+
+Use [Artistic Style](http://astyle.sourceforge.net/) (astyle) to format your code. Set the following rules for the astyle formatter:
+
+```
+style = ""
+indent-spaces = 2
+indent-classes = true
+indent-switches = true
+indent-cases = true
+indent-col1-comments = true
+pad-oper = true
+pad-header = true
+keep-one-line-statements = true
+```
+
+If you happen to use Sublime Text, [this astyle plugin](https://github.com/timonwong/SublimeAStyleFormatter) is helpful. Set the above rules in the user settings file.
--- /dev/null
+#!/bin/sh
+
+# use this script to package Firmata for distribution
+
+# package for Arduino 1.0.x
+mkdir -p temp/Firmata
+cp -r examples temp/Firmata
+cp -r extras temp/Firmata
+cp -r utility temp/Firmata
+cp *.cpp temp/Firmata
+cp *.h temp/Firmata
+cp keywords.txt temp/Firmata
+cp readme.md temp/Firmata
+cd temp
+find . -name "*.DS_Store" -type f -delete
+zip -r Firmata.zip ./Firmata/
+cd ..
+mv ./temp/Firmata.zip Arduino-1.0.x-Firmata-2.5.7.zip
+
+#package for Arduino 1.6.x and 1.8.x
+cp library.properties temp/Firmata
+cd temp/Firmata
+mv readme.md ./extras/
+mkdir src
+mv *.cpp ./src/
+mv *.h ./src/
+mv utility ./src/
+cd ..
+find . -name "*.DS_Store" -type f -delete
+zip -r Firmata.zip ./Firmata/
+cd ..
+mv ./temp/Firmata.zip Firmata-2.5.7.zip
+rm -r ./temp
--- /dev/null
+/*
+ * To run this test suite, you must first install the ArduinoUnit library
+ * to your Arduino/libraries/ directory.
+ * You can get ArduinoUnit here: https://github.com/mmurdoch/arduinounit
+ * Download version 2.0 or greater or install it via the Arduino library manager.
+ */
+
+#include <ArduinoUnit.h>
+#include <Firmata.h>
+
+void setup()
+{
+ Serial.begin(9600);
+}
+
+void loop()
+{
+ Test::run();
+}
+
+test(beginPrintsVersion)
+{
+ FakeStream stream;
+
+ Firmata.begin(stream);
+
+ char expected[] = {
+ REPORT_VERSION,
+ FIRMATA_PROTOCOL_MAJOR_VERSION,
+ FIRMATA_PROTOCOL_MINOR_VERSION,
+ 0
+ };
+ assertEqual(expected, stream.bytesWritten());
+}
+
+void processMessage(const byte *message, size_t length)
+{
+ FakeStream stream;
+ Firmata.begin(stream);
+
+ for (size_t i = 0; i < length; i++) {
+ stream.nextByte(message[i]);
+ Firmata.processInput();
+ }
+}
+
+byte _digitalPort;
+int _digitalPortValue;
+void writeToDigitalPort(byte port, int value)
+{
+ _digitalPort = port;
+ _digitalPortValue = value;
+}
+
+void setupDigitalPort()
+{
+ _digitalPort = 0;
+ _digitalPortValue = 0;
+}
+
+char * _receivedString;
+void handleStringCallback(char *str)
+{
+ _receivedString = str;
+}
+
+test(processWriteDigital_0)
+{
+ setupDigitalPort();
+ Firmata.attach(DIGITAL_MESSAGE, writeToDigitalPort);
+
+ byte message[] = { DIGITAL_MESSAGE, 0, 0 };
+ processMessage(message, 3);
+
+ assertEqual(0, _digitalPortValue);
+}
+
+test(processWriteDigital_127)
+{
+ setupDigitalPort();
+ Firmata.attach(DIGITAL_MESSAGE, writeToDigitalPort);
+
+ byte message[] = { DIGITAL_MESSAGE, 127, 0 };
+ processMessage(message, 3);
+
+ assertEqual(127, _digitalPortValue);
+}
+
+test(processWriteDigital_128)
+{
+ setupDigitalPort();
+ Firmata.attach(DIGITAL_MESSAGE, writeToDigitalPort);
+
+ byte message[] = { DIGITAL_MESSAGE, 0, 1 };
+ processMessage(message, 3);
+
+ assertEqual(128, _digitalPortValue);
+}
+
+test(processWriteLargestDigitalValue)
+{
+ setupDigitalPort();
+ Firmata.attach(DIGITAL_MESSAGE, writeToDigitalPort);
+
+ byte message[] = { DIGITAL_MESSAGE, 0x7F, 0x7F };
+ processMessage(message, 3);
+
+ // Maximum of 14 bits can be set (B0011111111111111)
+ assertEqual(0x3FFF, _digitalPortValue);
+}
+
+test(defaultDigitalWritePortIsZero)
+{
+ setupDigitalPort();
+ Firmata.attach(DIGITAL_MESSAGE, writeToDigitalPort);
+
+ byte message[] = { DIGITAL_MESSAGE, 0, 0 };
+ processMessage(message, 3);
+
+ assertEqual(0, _digitalPort);
+}
+
+test(specifiedDigitalWritePort)
+{
+ setupDigitalPort();
+ Firmata.attach(DIGITAL_MESSAGE, writeToDigitalPort);
+
+ byte message[] = { DIGITAL_MESSAGE + 1, 0, 0 };
+ processMessage(message, 3);
+
+ assertEqual(1, _digitalPort);
+}
+
+test(setFirmwareVersionDoesNotLeakMemory)
+{
+ Firmata.setFirmwareVersion(1, 0);
+ int initialMemory = freeMemory();
+
+ Firmata.setFirmwareVersion(1, 0);
+
+ assertEqual(0, initialMemory - freeMemory());
+}
+
+test(sendStringShouldEncode2BytesPerChar)
+{
+ FakeStream stream;
+ Firmata.begin(stream);
+ // reset the buffer because the firmware name string will be sent on Firmata.begin
+ stream.reset();
+
+ char testString[] = "hi!";
+ Firmata.sendString(testString);
+
+ byte expected[] = { START_SYSEX, STRING_DATA, 'h', 0, 'i', 0, '!', 0, END_SYSEX };
+
+ int len = stream.bytesWritten().length();
+ assertEqual(sizeof(expected), len);
+ for (byte i = 0; i < len; i++) {
+ assertEqual(expected[i], (byte)stream.bytesWritten().charAt(i));
+ }
+}
+
+test(receivedStringShouldDecodeFrom2BytesPerChar)
+{
+ Firmata.attach(STRING_DATA, handleStringCallback);
+
+ byte message[] = { START_SYSEX, STRING_DATA, 'b', 0, 'y', 0, 'e', 0, '!', 0, END_SYSEX };
+ processMessage(message, 11);
+
+ assertEqual("bye!", _receivedString);
+}
+
--- /dev/null
+# Testing Firmata
+
+Tests tests are written using the [ArduinoUnit](https://github.com/mmurdoch/arduinounit) library (version 2.0).
+
+Follow the instructions in the [ArduinoUnit readme](https://github.com/mmurdoch/arduinounit/blob/master/readme.md) to install the library.
+
+Compile and upload the test sketch as you would any other sketch. Then open the
+Serial Monitor to view the test results.
+
+If you make changes to Firmata.cpp, run the tests in /test/ to ensure
+that your changes have not produced any unexpected errors.
+
+You should also perform manual tests against actual hardware.
--- /dev/null
+/*
+ * Implementation is in BLEStream.h to avoid linker issues.
+ */
--- /dev/null
+/*
+ BLEStream.h
+
+ Based on BLESerial.cpp by Voita Molda
+ https://github.com/sandeepmistry/arduino-BLEPeripheral/blob/master/examples/serial/BLESerial.h
+
+ Last updated April 4th, 2016
+ */
+
+#ifndef _BLE_STREAM_H_
+#define _BLE_STREAM_H_
+
+#include <Arduino.h>
+#if defined(_VARIANT_ARDUINO_101_X_)
+#include <CurieBLE.h>
+#define _MAX_ATTR_DATA_LEN_ BLE_MAX_ATTR_DATA_LEN
+#else
+#include <BLEPeripheral.h>
+#define _MAX_ATTR_DATA_LEN_ BLE_ATTRIBUTE_MAX_VALUE_LENGTH
+#endif
+
+#define BLESTREAM_TXBUFFER_FLUSH_INTERVAL 80
+#define BLESTREAM_MIN_FLUSH_INTERVAL 8 // minimum interval for flushing the TX buffer
+
+// #define BLE_SERIAL_DEBUG
+
+class BLEStream : public BLEPeripheral, public Stream
+{
+ public:
+ BLEStream(unsigned char req = 0, unsigned char rdy = 0, unsigned char rst = 0);
+
+ void begin(...);
+ bool poll();
+ void end();
+ void setFlushInterval(int);
+
+ virtual int available(void);
+ virtual int peek(void);
+ virtual int read(void);
+ virtual void flush(void);
+ virtual size_t write(uint8_t byte);
+ using Print::write;
+ virtual operator bool();
+
+ private:
+ bool _connected;
+ unsigned long _flushed;
+ int _flushInterval;
+ static BLEStream* _instance;
+
+ size_t _rxHead;
+ size_t _rxTail;
+ size_t _rxCount() const;
+ unsigned char _rxBuffer[256];
+ size_t _txCount;
+ unsigned char _txBuffer[_MAX_ATTR_DATA_LEN_];
+
+ BLEService _uartService = BLEService("6E400001-B5A3-F393-E0A9-E50E24DCCA9E");
+ BLEDescriptor _uartNameDescriptor = BLEDescriptor("2901", "UART");
+ BLECharacteristic _rxCharacteristic = BLECharacteristic("6E400002-B5A3-F393-E0A9-E50E24DCCA9E", BLEWriteWithoutResponse, _MAX_ATTR_DATA_LEN_);
+ BLEDescriptor _rxNameDescriptor = BLEDescriptor("2901", "RX - Receive Data (Write)");
+ BLECharacteristic _txCharacteristic = BLECharacteristic("6E400003-B5A3-F393-E0A9-E50E24DCCA9E", BLENotify, _MAX_ATTR_DATA_LEN_);
+ BLEDescriptor _txNameDescriptor = BLEDescriptor("2901", "TX - Transfer Data (Notify)");
+
+ void _received(const unsigned char* data, size_t size);
+ static void _received(BLECentral& /*central*/, BLECharacteristic& rxCharacteristic);
+};
+
+
+/*
+ * BLEStream.cpp
+ * Copied here as a hack to avoid having to install the BLEPeripheral libarary even if it's
+ * not needed.
+ */
+
+BLEStream* BLEStream::_instance = NULL;
+
+BLEStream::BLEStream(unsigned char req, unsigned char rdy, unsigned char rst) :
+#if defined(_VARIANT_ARDUINO_101_X_)
+ BLEPeripheral()
+#else
+ BLEPeripheral(req, rdy, rst)
+#endif
+{
+ this->_txCount = 0;
+ this->_rxHead = this->_rxTail = 0;
+ this->_flushed = 0;
+ this->_flushInterval = BLESTREAM_TXBUFFER_FLUSH_INTERVAL;
+ BLEStream::_instance = this;
+
+ addAttribute(this->_uartService);
+ addAttribute(this->_uartNameDescriptor);
+ setAdvertisedServiceUuid(this->_uartService.uuid());
+ addAttribute(this->_rxCharacteristic);
+ addAttribute(this->_rxNameDescriptor);
+ this->_rxCharacteristic.setEventHandler(BLEWritten, BLEStream::_received);
+ addAttribute(this->_txCharacteristic);
+ addAttribute(this->_txNameDescriptor);
+}
+
+void BLEStream::begin(...)
+{
+ BLEPeripheral::begin();
+#ifdef BLE_SERIAL_DEBUG
+ Serial.println(F("BLEStream::begin()"));
+#endif
+}
+
+bool BLEStream::poll()
+{
+ // BLEPeripheral::poll is called each time connected() is called
+ this->_connected = BLEPeripheral::connected();
+ if (millis() > this->_flushed + this->_flushInterval) {
+ flush();
+ }
+ return this->_connected;
+}
+
+void BLEStream::end()
+{
+ this->_rxCharacteristic.setEventHandler(BLEWritten, (void(*)(BLECentral&, BLECharacteristic&))NULL);
+ this->_rxHead = this->_rxTail = 0;
+ flush();
+ BLEPeripheral::disconnect();
+}
+
+int BLEStream::available(void)
+{
+// BLEPeripheral::poll only calls delay(1) in CurieBLE so skipping it here to avoid the delay
+#ifndef _VARIANT_ARDUINO_101_X_
+ // TODO Need to do more testing to determine if all of these calls to BLEPeripheral::poll are
+ // actually necessary. Seems to run fine without them, but only minimal testing so far.
+ BLEPeripheral::poll();
+#endif
+ int retval = (this->_rxHead - this->_rxTail + sizeof(this->_rxBuffer)) % sizeof(this->_rxBuffer);
+#ifdef BLE_SERIAL_DEBUG
+ if (retval > 0) {
+ Serial.print(F("BLEStream::available() = "));
+ Serial.println(retval);
+ }
+#endif
+ return retval;
+}
+
+int BLEStream::peek(void)
+{
+#ifndef _VARIANT_ARDUINO_101_X_
+ BLEPeripheral::poll();
+#endif
+ if (this->_rxTail == this->_rxHead) return -1;
+ uint8_t byte = this->_rxBuffer[this->_rxTail];
+#ifdef BLE_SERIAL_DEBUG
+ Serial.print(F("BLEStream::peek() = 0x"));
+ Serial.println(byte, HEX);
+#endif
+ return byte;
+}
+
+int BLEStream::read(void)
+{
+#ifndef _VARIANT_ARDUINO_101_X_
+ BLEPeripheral::poll();
+#endif
+ if (this->_rxTail == this->_rxHead) return -1;
+ this->_rxTail = (this->_rxTail + 1) % sizeof(this->_rxBuffer);
+ uint8_t byte = this->_rxBuffer[this->_rxTail];
+#ifdef BLE_SERIAL_DEBUG
+ Serial.print(F("BLEStream::read() = 0x"));
+ Serial.println(byte, HEX);
+#endif
+ return byte;
+}
+
+void BLEStream::flush(void)
+{
+ if (this->_txCount == 0) return;
+#ifndef _VARIANT_ARDUINO_101_X_
+ // ensure there are available packets before sending
+ while(!this->_txCharacteristic.canNotify()) {
+ BLEPeripheral::poll();
+ }
+#endif
+ this->_txCharacteristic.setValue(this->_txBuffer, this->_txCount);
+ this->_flushed = millis();
+ this->_txCount = 0;
+#ifdef BLE_SERIAL_DEBUG
+ Serial.println(F("BLEStream::flush()"));
+#endif
+}
+
+size_t BLEStream::write(uint8_t byte)
+{
+#ifndef _VARIANT_ARDUINO_101_X_
+ BLEPeripheral::poll();
+#endif
+ if (this->_txCharacteristic.subscribed() == false) return 0;
+ this->_txBuffer[this->_txCount++] = byte;
+ if (this->_txCount == sizeof(this->_txBuffer)) flush();
+#ifdef BLE_SERIAL_DEBUG
+ Serial.print(F("BLEStream::write( 0x"));
+ Serial.print(byte, HEX);
+ Serial.println(F(") = 1"));
+#endif
+ return 1;
+}
+
+BLEStream::operator bool()
+{
+ bool retval = this->_connected = BLEPeripheral::connected();
+#ifdef BLE_SERIAL_DEBUG
+ Serial.print(F("BLEStream::operator bool() = "));
+ Serial.println(retval);
+#endif
+ return retval;
+}
+
+void BLEStream::setFlushInterval(int interval)
+{
+ if (interval > BLESTREAM_MIN_FLUSH_INTERVAL) {
+ this->_flushInterval = interval;
+ }
+}
+
+void BLEStream::_received(const unsigned char* data, size_t size)
+{
+ for (size_t i = 0; i < size; i++) {
+ this->_rxHead = (this->_rxHead + 1) % sizeof(this->_rxBuffer);
+ this->_rxBuffer[this->_rxHead] = data[i];
+ }
+#ifdef BLE_SERIAL_DEBUG
+ Serial.print(F("BLEStream::received("));
+ for (int i = 0; i < size; i++) Serial.print(data[i], HEX);
+ Serial.println(F(")"));
+#endif
+}
+
+void BLEStream::_received(BLECentral& /*central*/, BLECharacteristic& rxCharacteristic)
+{
+ BLEStream::_instance->_received(rxCharacteristic.value(), rxCharacteristic.valueLength());
+}
+
+
+#endif // _BLE_STREAM_H_
--- /dev/null
+/*
+ * Implementation is in EthernetClientStream.h to avoid linker issues.
+ */
--- /dev/null
+/*
+ EthernetClientStream.h
+ An Arduino-Stream that wraps an instance of Client reconnecting to
+ the remote-ip in a transparent way. A disconnected client may be
+ recognized by the returnvalues -1 from calls to peek or read and
+ a 0 from calls to write.
+
+ Copyright (C) 2013 Norbert Truchsess. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+
+ Last updated June 18th, 2016
+ */
+
+#ifndef ETHERNETCLIENTSTREAM_H
+#define ETHERNETCLIENTSTREAM_H
+
+#include <inttypes.h>
+#include <Stream.h>
+
+//#define SERIAL_DEBUG
+#include "firmataDebug.h"
+
+#define MILLIS_RECONNECT 5000
+
+class EthernetClientStream : public Stream
+{
+ public:
+ EthernetClientStream(Client &client, IPAddress localip, IPAddress ip, const char* host, uint16_t port);
+ int available();
+ int read();
+ int peek();
+ void flush();
+ size_t write(uint8_t);
+ void maintain(IPAddress localip);
+
+ private:
+ Client &client;
+ IPAddress localip;
+ IPAddress ip;
+ const char* host;
+ uint16_t port;
+ bool connected;
+ uint32_t time_connect;
+ bool maintain();
+ void stop();
+};
+
+
+/*
+ * EthernetClientStream.cpp
+ * Copied here as a hack to linker issues with 3rd party board packages that don't properly
+ * implement the Arduino network APIs.
+ */
+EthernetClientStream::EthernetClientStream(Client &client, IPAddress localip, IPAddress ip, const char* host, uint16_t port)
+ : client(client),
+ localip(localip),
+ ip(ip),
+ host(host),
+ port(port),
+ connected(false)
+{
+}
+
+int
+EthernetClientStream::available()
+{
+ return maintain() ? client.available() : 0;
+}
+
+int
+EthernetClientStream::read()
+{
+ return maintain() ? client.read() : -1;
+}
+
+int
+EthernetClientStream::peek()
+{
+ return maintain() ? client.peek() : -1;
+}
+
+void EthernetClientStream::flush()
+{
+ if (maintain())
+ client.flush();
+}
+
+size_t
+EthernetClientStream::write(uint8_t c)
+{
+ return maintain() ? client.write(c) : 0;
+}
+
+void
+EthernetClientStream::maintain(IPAddress localip)
+{
+ // ensure the local IP is updated in the case that it is changed by the DHCP server
+ if (this->localip != localip) {
+ this->localip = localip;
+ if (connected)
+ stop();
+ }
+}
+
+void
+EthernetClientStream::stop()
+{
+ client.stop();
+ connected = false;
+ time_connect = millis();
+}
+
+bool
+EthernetClientStream::maintain()
+{
+ if (client && client.connected())
+ return true;
+
+ if (connected) {
+ stop();
+ }
+ // if the client is disconnected, attempt to reconnect every 5 seconds
+ else if (millis() - time_connect >= MILLIS_RECONNECT) {
+ connected = host ? client.connect(host, port) : client.connect(ip, port);
+ if (!connected) {
+ time_connect = millis();
+ DEBUG_PRINTLN("Connection failed. Attempting to reconnect...");
+ } else {
+ DEBUG_PRINTLN("Connected");
+ }
+ }
+ return connected;
+}
+
+#endif /* ETHERNETCLIENTSTREAM_H */
--- /dev/null
+/*
+ * Implementation is in EthernetServerStream.h to avoid linker issues.
+ */
--- /dev/null
+/*
+ EthernetServerStream.h
+
+ Copyright (C) 2017 Marc Josef Pees. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+
+ Last updated July 10th, 2017
+ */
+
+#ifndef ETHERNETSERVERSTREAM_H
+#define ETHERNETSERVERSTREAM_H
+
+#include <inttypes.h>
+#include <Stream.h>
+#include <Ethernet.h>
+
+//#define SERIAL_DEBUG
+#include "firmataDebug.h"
+
+class EthernetServerStream : public Stream
+{
+ public:
+ EthernetServerStream(IPAddress localip, uint16_t port);
+ int available();
+ int read();
+ int peek();
+ void flush();
+ size_t write(uint8_t);
+ void maintain(IPAddress localip);
+
+ private:
+ EthernetClient client;
+ IPAddress localip;
+ uint16_t port;
+ bool connected;
+ bool maintain();
+ void stop();
+
+ protected:
+ EthernetServer server = EthernetServer(3030);
+ bool listening = false;
+ bool connect_client();
+};
+
+
+/*
+ * EthernetServerStream.cpp
+ * Copied here as a hack to linker issues with 3rd party board packages that don't properly
+ * implement the Arduino network APIs.
+ */
+EthernetServerStream::EthernetServerStream(IPAddress localip, uint16_t port)
+ : localip(localip),
+ port(port),
+ connected(false)
+{
+}
+
+bool EthernetServerStream::connect_client()
+ {
+ if ( connected )
+ {
+ if ( client && client.connected() ) return true;
+ stop();
+ }
+
+ EthernetClient newClient = server.available();
+ if ( !newClient ) return false;
+ client = newClient;
+ connected = true;
+ DEBUG_PRINTLN("Connected");
+ return true;
+ }
+
+int
+EthernetServerStream::available()
+{
+ return maintain() ? client.available() : 0;
+}
+
+int
+EthernetServerStream::read()
+{
+ return maintain() ? client.read() : -1;
+}
+
+int
+EthernetServerStream::peek()
+{
+ return maintain() ? client.peek() : -1;
+}
+
+void EthernetServerStream::flush()
+{
+ if (maintain())
+ client.flush();
+}
+
+size_t
+EthernetServerStream::write(uint8_t c)
+{
+ return maintain() ? client.write(c) : 0;
+}
+
+void
+EthernetServerStream::maintain(IPAddress localip)
+{
+ // ensure the local IP is updated in the case that it is changed by the DHCP server
+ if (this->localip != localip) {
+ this->localip = localip;
+ if (connected)
+ stop();
+ }
+}
+
+void
+EthernetServerStream::stop()
+{
+ if(client)
+ {
+ client.stop();
+ }
+ connected = false;
+}
+
+bool
+EthernetServerStream::maintain()
+{
+ if (connect_client()) return true;
+
+ stop();
+
+ if(!listening)
+ {
+ server = EthernetServer(port);
+ server.begin();
+ listening = true;
+ }
+ return false;
+}
+
+#endif /* ETHERNETSERVERSTREAM_H */
--- /dev/null
+/*
+ FirmataFeature.h
+ Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.
+ Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved.
+ Copyright (C) 2009 Shigeru Kobayashi. All rights reserved.
+ Copyright (C) 2013 Norbert Truchsess. All rights reserved.
+ Copyright (C) 2009-2016 Jeff Hoefs. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ Interface for Firmata feature classes.
+
+ This version of FirmataFeature.h differs from the ConfigurableFirmata
+ version in the following ways:
+
+ - Imports Firmata.h rather than ConfigurableFirmata.h
+
+ See file LICENSE.txt for further informations on licensing terms.
+*/
+
+#ifndef FirmataFeature_h
+#define FirmataFeature_h
+
+#include <Firmata.h>
+
+class FirmataFeature
+{
+ public:
+ virtual void handleCapability(byte pin) = 0;
+ virtual boolean handlePinMode(byte pin, int mode) = 0;
+ virtual boolean handleSysex(byte command, byte argc, byte* argv) = 0;
+ virtual void reset() = 0;
+};
+
+#endif
--- /dev/null
+/*
+ SerialFirmata.cpp
+ Copyright (C) 2016 Jeff Hoefs. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+
+ This version of SerialFirmata.cpp differs from the ConfigurableFirmata
+ version in the following ways:
+
+ - handlePinMode calls Firmata::setPinMode
+
+ Last updated October 16th, 2016
+*/
+
+#include "SerialFirmata.h"
+
+SerialFirmata::SerialFirmata()
+{
+#if defined(SoftwareSerial_h)
+ swSerial0 = NULL;
+ swSerial1 = NULL;
+ swSerial2 = NULL;
+ swSerial3 = NULL;
+#endif
+
+ serialIndex = -1;
+}
+
+boolean SerialFirmata::handlePinMode(byte pin, int mode)
+{
+ // used for both HW and SW serial
+ if (mode == PIN_MODE_SERIAL) {
+ Firmata.setPinMode(pin, PIN_MODE_SERIAL);
+ return true;
+ }
+ return false;
+}
+
+void SerialFirmata::handleCapability(byte pin)
+{
+ if (IS_PIN_SERIAL(pin)) {
+ Firmata.write(PIN_MODE_SERIAL);
+ Firmata.write(getSerialPinType(pin));
+ }
+}
+
+boolean SerialFirmata::handleSysex(byte command, byte argc, byte *argv)
+{
+ if (command == SERIAL_MESSAGE) {
+
+ Stream *serialPort;
+ byte mode = argv[0] & SERIAL_MODE_MASK;
+ byte portId = argv[0] & SERIAL_PORT_ID_MASK;
+
+ switch (mode) {
+ case SERIAL_CONFIG:
+ {
+ long baud = (long)argv[1] | ((long)argv[2] << 7) | ((long)argv[3] << 14);
+ serial_pins pins;
+
+ if (portId < 8) {
+ serialPort = getPortFromId(portId);
+ if (serialPort != NULL) {
+ pins = getSerialPinNumbers(portId);
+ if (pins.rx != 0 && pins.tx != 0) {
+ Firmata.setPinMode(pins.rx, PIN_MODE_SERIAL);
+ Firmata.setPinMode(pins.tx, PIN_MODE_SERIAL);
+ // Fixes an issue where some serial devices would not work properly with Arduino Due
+ // because all Arduino pins are set to OUTPUT by default in StandardFirmata.
+ pinMode(pins.rx, INPUT);
+ }
+ ((HardwareSerial*)serialPort)->begin(baud);
+ }
+ } else {
+#if defined(SoftwareSerial_h)
+ byte swTxPin, swRxPin;
+ if (argc > 4) {
+ swRxPin = argv[4];
+ swTxPin = argv[5];
+ } else {
+ // RX and TX pins must be specified when using SW serial
+ Firmata.sendString("Specify serial RX and TX pins");
+ return false;
+ }
+ switch (portId) {
+ case SW_SERIAL0:
+ if (swSerial0 == NULL) {
+ swSerial0 = new SoftwareSerial(swRxPin, swTxPin);
+ }
+ break;
+ case SW_SERIAL1:
+ if (swSerial1 == NULL) {
+ swSerial1 = new SoftwareSerial(swRxPin, swTxPin);
+ }
+ break;
+ case SW_SERIAL2:
+ if (swSerial2 == NULL) {
+ swSerial2 = new SoftwareSerial(swRxPin, swTxPin);
+ }
+ break;
+ case SW_SERIAL3:
+ if (swSerial3 == NULL) {
+ swSerial3 = new SoftwareSerial(swRxPin, swTxPin);
+ }
+ break;
+ }
+ serialPort = getPortFromId(portId);
+ if (serialPort != NULL) {
+ Firmata.setPinMode(swRxPin, PIN_MODE_SERIAL);
+ Firmata.setPinMode(swTxPin, PIN_MODE_SERIAL);
+ ((SoftwareSerial*)serialPort)->begin(baud);
+ }
+#endif
+ }
+ break; // SERIAL_CONFIG
+ }
+ case SERIAL_WRITE:
+ {
+ byte data;
+ serialPort = getPortFromId(portId);
+ if (serialPort == NULL) {
+ break;
+ }
+ for (byte i = 1; i < argc; i += 2) {
+ data = argv[i] + (argv[i + 1] << 7);
+ serialPort->write(data);
+ }
+ break; // SERIAL_WRITE
+ }
+ case SERIAL_READ:
+ if (argv[1] == SERIAL_READ_CONTINUOUSLY) {
+ if (serialIndex + 1 >= MAX_SERIAL_PORTS) {
+ break;
+ }
+
+ if (argc > 2) {
+ // maximum number of bytes to read from buffer per iteration of loop()
+ serialBytesToRead[portId] = (int)argv[2] | ((int)argv[3] << 7);
+ } else {
+ // read all available bytes per iteration of loop()
+ serialBytesToRead[portId] = 0;
+ }
+ serialIndex++;
+ reportSerial[serialIndex] = portId;
+ } else if (argv[1] == SERIAL_STOP_READING) {
+ byte serialIndexToSkip = 0;
+ if (serialIndex <= 0) {
+ serialIndex = -1;
+ } else {
+ for (byte i = 0; i < serialIndex + 1; i++) {
+ if (reportSerial[i] == portId) {
+ serialIndexToSkip = i;
+ break;
+ }
+ }
+ // shift elements over to fill space left by removed element
+ for (byte i = serialIndexToSkip; i < serialIndex + 1; i++) {
+ if (i < MAX_SERIAL_PORTS) {
+ reportSerial[i] = reportSerial[i + 1];
+ }
+ }
+ serialIndex--;
+ }
+ }
+ break; // SERIAL_READ
+ case SERIAL_CLOSE:
+ serialPort = getPortFromId(portId);
+ if (serialPort != NULL) {
+ if (portId < 8) {
+ ((HardwareSerial*)serialPort)->end();
+ } else {
+#if defined(SoftwareSerial_h)
+ ((SoftwareSerial*)serialPort)->end();
+ if (serialPort != NULL) {
+ free(serialPort);
+ serialPort = NULL;
+ }
+#endif
+ }
+ }
+ break; // SERIAL_CLOSE
+ case SERIAL_FLUSH:
+ serialPort = getPortFromId(portId);
+ if (serialPort != NULL) {
+ getPortFromId(portId)->flush();
+ }
+ break; // SERIAL_FLUSH
+#if defined(SoftwareSerial_h)
+ case SERIAL_LISTEN:
+ // can only call listen() on software serial ports
+ if (portId > 7) {
+ serialPort = getPortFromId(portId);
+ if (serialPort != NULL) {
+ ((SoftwareSerial*)serialPort)->listen();
+ }
+ }
+ break; // SERIAL_LISTEN
+#endif
+ } // end switch
+ return true;
+ }
+ return false;
+}
+
+void SerialFirmata::update()
+{
+ checkSerial();
+}
+
+void SerialFirmata::reset()
+{
+#if defined(SoftwareSerial_h)
+ Stream *serialPort;
+ // free memory allocated for SoftwareSerial ports
+ for (byte i = SW_SERIAL0; i < SW_SERIAL3 + 1; i++) {
+ serialPort = getPortFromId(i);
+ if (serialPort != NULL) {
+ free(serialPort);
+ serialPort = NULL;
+ }
+ }
+#endif
+
+ serialIndex = -1;
+ for (byte i = 0; i < SERIAL_READ_ARR_LEN; i++) {
+ serialBytesToRead[i] = 0;
+ }
+}
+
+// get a pointer to the serial port associated with the specified port id
+Stream* SerialFirmata::getPortFromId(byte portId)
+{
+ switch (portId) {
+ case HW_SERIAL0:
+ // block use of Serial (typically pins 0 and 1) until ability to reclaim Serial is implemented
+ //return &Serial;
+ return NULL;
+#if defined(PIN_SERIAL1_RX)
+ case HW_SERIAL1:
+ return &Serial1;
+#endif
+#if defined(PIN_SERIAL2_RX)
+ case HW_SERIAL2:
+ return &Serial2;
+#endif
+#if defined(PIN_SERIAL3_RX)
+ case HW_SERIAL3:
+ return &Serial3;
+#endif
+#if defined(SoftwareSerial_h)
+ case SW_SERIAL0:
+ if (swSerial0 != NULL) {
+ // instances of SoftwareSerial are already pointers so simply return the instance
+ return swSerial0;
+ }
+ break;
+ case SW_SERIAL1:
+ if (swSerial1 != NULL) {
+ return swSerial1;
+ }
+ break;
+ case SW_SERIAL2:
+ if (swSerial2 != NULL) {
+ return swSerial2;
+ }
+ break;
+ case SW_SERIAL3:
+ if (swSerial3 != NULL) {
+ return swSerial3;
+ }
+ break;
+#endif
+ }
+ return NULL;
+}
+
+// Check serial ports that have READ_CONTINUOUS mode set and relay any data
+// for each port to the device attached to that port.
+void SerialFirmata::checkSerial()
+{
+ byte portId, serialData;
+ int bytesToRead = 0;
+ int numBytesToRead = 0;
+ Stream* serialPort;
+
+ if (serialIndex > -1) {
+
+ // loop through all reporting (READ_CONTINUOUS) serial ports
+ for (byte i = 0; i < serialIndex + 1; i++) {
+ portId = reportSerial[i];
+ bytesToRead = serialBytesToRead[portId];
+ serialPort = getPortFromId(portId);
+ if (serialPort == NULL) {
+ continue;
+ }
+#if defined(SoftwareSerial_h)
+ // only the SoftwareSerial port that is "listening" can read data
+ if (portId > 7 && !((SoftwareSerial*)serialPort)->isListening()) {
+ continue;
+ }
+#endif
+ if (serialPort->available() > 0) {
+ Firmata.write(START_SYSEX);
+ Firmata.write(SERIAL_MESSAGE);
+ Firmata.write(SERIAL_REPLY | portId);
+
+ if (bytesToRead == 0 || (serialPort->available() <= bytesToRead)) {
+ numBytesToRead = serialPort->available();
+ } else {
+ numBytesToRead = bytesToRead;
+ }
+
+ // relay serial data to the serial device
+ while (numBytesToRead > 0) {
+ serialData = serialPort->read();
+ Firmata.write(serialData & 0x7F);
+ Firmata.write((serialData >> 7) & 0x7F);
+ numBytesToRead--;
+ }
+ Firmata.write(END_SYSEX);
+ }
+
+ }
+ }
+}
--- /dev/null
+/*
+ SerialFirmata.h
+ Copyright (C) 2016 Jeff Hoefs. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+
+ This version of SerialFirmata.h differs from the ConfigurableFirmata
+ version in the following ways:
+
+ - Defines FIRMATA_SERIAL_FEATURE (could add to Configurable version as well)
+ - Imports Firmata.h rather than ConfigurableFirmata.h
+
+ Last updated October 16th, 2016
+*/
+
+#ifndef SerialFirmata_h
+#define SerialFirmata_h
+
+#include <Firmata.h>
+#include "FirmataFeature.h"
+// SoftwareSerial is currently only supported for AVR-based boards and the Arduino 101.
+// Limited to Arduino 1.6.6 or higher because Arduino builder cannot find SoftwareSerial
+// prior to this release.
+#if (ARDUINO > 10605) && (defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_ARC32))
+#include <SoftwareSerial.h>
+#endif
+
+#define FIRMATA_SERIAL_FEATURE
+
+// Serial port Ids
+#define HW_SERIAL0 0x00
+#define HW_SERIAL1 0x01
+#define HW_SERIAL2 0x02
+#define HW_SERIAL3 0x03
+// extensible up to 0x07
+
+#define SW_SERIAL0 0x08
+#define SW_SERIAL1 0x09
+#define SW_SERIAL2 0x0A
+#define SW_SERIAL3 0x0B
+// extensible up to 0x0F
+
+#define SERIAL_PORT_ID_MASK 0x0F
+#define MAX_SERIAL_PORTS 8
+#define SERIAL_READ_ARR_LEN 12
+
+// map configuration query response resolution value to serial pin type
+#define RES_RX1 0x02
+#define RES_TX1 0x03
+#define RES_RX2 0x04
+#define RES_TX2 0x05
+#define RES_RX3 0x06
+#define RES_TX3 0x07
+
+// Serial command bytes
+#define SERIAL_CONFIG 0x10
+#define SERIAL_WRITE 0x20
+#define SERIAL_READ 0x30
+#define SERIAL_REPLY 0x40
+#define SERIAL_CLOSE 0x50
+#define SERIAL_FLUSH 0x60
+#define SERIAL_LISTEN 0x70
+
+// Serial read modes
+#define SERIAL_READ_CONTINUOUSLY 0x00
+#define SERIAL_STOP_READING 0x01
+#define SERIAL_MODE_MASK 0xF0
+
+namespace {
+
+ struct serial_pins {
+ uint8_t rx;
+ uint8_t tx;
+ };
+
+ /*
+ * Get the serial serial pin type (RX1, TX1, RX2, TX2, etc) for the specified pin.
+ */
+ inline uint8_t getSerialPinType(uint8_t pin) {
+ #if defined(PIN_SERIAL_RX)
+ // TODO when use of HW_SERIAL0 is enabled
+ #endif
+ #if defined(PIN_SERIAL1_RX)
+ if (pin == PIN_SERIAL1_RX) return RES_RX1;
+ if (pin == PIN_SERIAL1_TX) return RES_TX1;
+ #endif
+ #if defined(PIN_SERIAL2_RX)
+ if (pin == PIN_SERIAL2_RX) return RES_RX2;
+ if (pin == PIN_SERIAL2_TX) return RES_TX2;
+ #endif
+ #if defined(PIN_SERIAL3_RX)
+ if (pin == PIN_SERIAL3_RX) return RES_RX3;
+ if (pin == PIN_SERIAL3_TX) return RES_TX3;
+ #endif
+ return 0;
+ }
+
+ /*
+ * Get the RX and TX pins numbers for the specified HW serial port.
+ */
+ inline serial_pins getSerialPinNumbers(uint8_t portId) {
+ serial_pins pins;
+ switch (portId) {
+ #if defined(PIN_SERIAL_RX)
+ // case HW_SERIAL0:
+ // // TODO when use of HW_SERIAL0 is enabled
+ // break;
+ #endif
+ #if defined(PIN_SERIAL1_RX)
+ case HW_SERIAL1:
+ pins.rx = PIN_SERIAL1_RX;
+ pins.tx = PIN_SERIAL1_TX;
+ break;
+ #endif
+ #if defined(PIN_SERIAL2_RX)
+ case HW_SERIAL2:
+ pins.rx = PIN_SERIAL2_RX;
+ pins.tx = PIN_SERIAL2_TX;
+ break;
+ #endif
+ #if defined(PIN_SERIAL3_RX)
+ case HW_SERIAL3:
+ pins.rx = PIN_SERIAL3_RX;
+ pins.tx = PIN_SERIAL3_TX;
+ break;
+ #endif
+ default:
+ pins.rx = 0;
+ pins.tx = 0;
+ }
+ return pins;
+ }
+
+} // end namespace
+
+
+class SerialFirmata: public FirmataFeature
+{
+ public:
+ SerialFirmata();
+ boolean handlePinMode(byte pin, int mode);
+ void handleCapability(byte pin);
+ boolean handleSysex(byte command, byte argc, byte* argv);
+ void update();
+ void reset();
+ void checkSerial();
+
+ private:
+ byte reportSerial[MAX_SERIAL_PORTS];
+ int serialBytesToRead[SERIAL_READ_ARR_LEN];
+ signed char serialIndex;
+
+#if defined(SoftwareSerial_h)
+ Stream *swSerial0;
+ Stream *swSerial1;
+ Stream *swSerial2;
+ Stream *swSerial3;
+#endif
+
+ Stream* getPortFromId(byte portId);
+
+};
+
+#endif /* SerialFirmata_h */
--- /dev/null
+/*
+ WiFiClientStream.h
+
+ An Arduino Stream that wraps an instance of a WiFiClient. For use
+ with legacy Arduino WiFi shield and other boards and shields that
+ are compatible with the Arduino WiFi library.
+
+ Copyright (C) 2016 Jens B. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+
+ Parts of this class are based on
+
+ - EthernetClientStream - Copyright (C) 2013 Norbert Truchsess. All rights reserved.
+
+ published under the same license.
+
+ Last updated April 23rd, 2016
+ */
+
+#ifndef WIFI_CLIENT_STREAM_H
+#define WIFI_CLIENT_STREAM_H
+
+#include "WiFiStream.h"
+
+#define MILLIS_RECONNECT 5000
+
+class WiFiClientStream : public WiFiStream
+{
+protected:
+ uint32_t _time_connect = 0;
+
+ /**
+ * check if TCP client is connected
+ * @return true if connected
+ */
+ virtual inline bool connect_client()
+ {
+ if ( _connected )
+ {
+ if ( _client && _client.connected() ) return true;
+ stop();
+ }
+
+ // active TCP connect
+ if ( WiFi.status() == WL_CONNECTED )
+ {
+ // if the client is disconnected, try to reconnect every 5 seconds
+ if ( millis() - _time_connect >= MILLIS_RECONNECT )
+ {
+ _connected = _client.connect( _remote_ip, _port );
+ if ( !_connected )
+ {
+ _time_connect = millis();
+ }
+ else if ( _currentHostConnectionCallback )
+ {
+ (*_currentHostConnectionCallback)(HOST_CONNECTION_CONNECTED);
+ }
+ }
+ }
+
+ return _connected;
+ }
+
+public:
+ /**
+ * create a WiFi stream with a TCP client
+ */
+ WiFiClientStream(IPAddress server_ip, uint16_t server_port) : WiFiStream(server_ip, server_port) {}
+
+ /**
+ * maintain WiFi and TCP connection
+ * @return true if WiFi and TCP connection are established
+ */
+ virtual inline bool maintain()
+ {
+ return connect_client();
+ }
+
+ /**
+ * stop client connection
+ */
+ virtual inline void stop()
+ {
+ if ( _client)
+ {
+ _client.stop();
+ if ( _currentHostConnectionCallback )
+ {
+ (*_currentHostConnectionCallback)(HOST_CONNECTION_DISCONNECTED);
+ }
+ }
+ _connected = false;
+ _time_connect = millis();
+ }
+
+};
+
+#endif //WIFI_CLIENT_STREAM_H
--- /dev/null
+/*
+ WiFiServerStream.h
+
+ An Arduino Stream extension for a WiFiClient or WiFiServer to be used
+ with legacy Arduino WiFi shield and other boards and shields that
+ are compatible with the Arduino WiFi library.
+
+ Copyright (C) 2016 Jens B. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+
+ Parts of this class are based on
+
+ - WiFiStream - Copyright (C) 2015-2016 Jesse Frush. All rights reserved.
+
+ published under the same license.
+
+ Last updated April 23rd, 2016
+ */
+
+#ifndef WIFI_SERVER_STREAM_H
+#define WIFI_SERVER_STREAM_H
+
+#include "WiFiStream.h"
+
+class WiFiServerStream : public WiFiStream
+{
+protected:
+ WiFiServer _server = WiFiServer(3030);
+ bool _listening = false;
+
+ /**
+ * check if TCP client is connected
+ * @return true if connected
+ */
+ virtual inline bool connect_client()
+ {
+ if ( _connected )
+ {
+ if ( _client && _client.connected() ) return true;
+ stop();
+ }
+
+ // passive TCP connect (accept)
+ WiFiClient newClient = _server.available();
+ if ( !newClient ) return false;
+ _client = newClient;
+ _connected = true;
+ if ( _currentHostConnectionCallback )
+ {
+ (*_currentHostConnectionCallback)(HOST_CONNECTION_CONNECTED);
+ }
+
+ return true;
+ }
+
+public:
+ /**
+ * create a WiFi stream with a TCP server
+ */
+ WiFiServerStream(uint16_t server_port) : WiFiStream(server_port) {}
+
+ /**
+ * maintain WiFi and TCP connection
+ * @return true if WiFi and TCP connection are established
+ */
+ virtual inline bool maintain()
+ {
+ if ( connect_client() ) return true;
+
+ stop();
+
+ if ( !_listening && WiFi.status() == WL_CONNECTED )
+ {
+ // start TCP server after first WiFi connect
+ _server = WiFiServer(_port);
+ _server.begin();
+ _listening = true;
+ }
+
+ return false;
+ }
+
+ /**
+ * stop client connection
+ */
+ virtual inline void stop()
+ {
+ if ( _client)
+ {
+ _client.stop();
+ if ( _currentHostConnectionCallback )
+ {
+ (*_currentHostConnectionCallback)(HOST_CONNECTION_DISCONNECTED);
+ }
+ }
+ _connected = false;
+ }
+
+};
+
+#endif //WIFI_SERVER_STREAM_H
--- /dev/null
+/*
+ * Implementation is in WiFiStream.h to avoid linker issues. Legacy WiFi and modern WiFi101 both define WiFiClass which
+ * will cause linker errors whenever Firmata.h is included.
+ */
--- /dev/null
+/*
+ WiFiStream.h
+
+ An Arduino Stream extension for a WiFiClient or WiFiServer to be used
+ with legacy Arduino WiFi shield and other boards and shields that
+ are compatible with the Arduino WiFi library.
+
+ Copyright (C) 2015-2016 Jesse Frush. All rights reserved.
+ Copyright (C) 2016 Jens B. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ See file LICENSE.txt for further informations on licensing terms.
+
+ Last updated April 23rd, 2016
+ */
+
+#ifndef WIFI_STREAM_H
+#define WIFI_STREAM_H
+
+#include <inttypes.h>
+#include <Stream.h>
+
+#define HOST_CONNECTION_DISCONNECTED 0
+#define HOST_CONNECTION_CONNECTED 1
+
+extern "C" {
+ // callback function types
+ typedef void (*hostConnectionCallbackFunction)(byte);
+}
+
+class WiFiStream : public Stream
+{
+protected:
+ WiFiClient _client;
+ bool _connected = false;
+ hostConnectionCallbackFunction _currentHostConnectionCallback;
+
+ //configuration members
+ IPAddress _local_ip; // DHCP
+ IPAddress _subnet;
+ IPAddress _gateway;
+ IPAddress _remote_ip;
+ uint16_t _port;
+ uint8_t _key_idx; //WEP
+ const char *_key = nullptr; //WEP
+ const char *_passphrase = nullptr; //WPA
+ char *_ssid = nullptr;
+
+ /**
+ * check if TCP client is connected
+ * @return true if connected
+ */
+ virtual bool connect_client() = 0;
+
+public:
+ /** constructor for TCP server */
+ WiFiStream(uint16_t server_port) : _port(server_port) {}
+
+ /** constructor for TCP client */
+ WiFiStream(IPAddress server_ip, uint16_t server_port) : _remote_ip(server_ip), _port(server_port) {}
+
+ inline void attach( hostConnectionCallbackFunction newFunction ) { _currentHostConnectionCallback = newFunction; }
+
+/******************************************************************************
+ * network configuration
+ ******************************************************************************/
+
+#ifndef ESP8266
+ /**
+ * configure a static local IP address without defining the local network
+ * DHCP will be used as long as local IP address is not defined
+ */
+ inline void config(IPAddress local_ip)
+ {
+ _local_ip = local_ip;
+ WiFi.config( local_ip );
+ }
+#endif
+
+ /**
+ * configure a static local IP address
+ * DHCP will be used as long as local IP address is not defined
+ */
+ inline void config(IPAddress local_ip, IPAddress gateway, IPAddress subnet)
+ {
+ _local_ip = local_ip;
+ _subnet = subnet;
+ _gateway = gateway;
+#ifndef ESP8266
+ WiFi.config( local_ip, IPAddress(0, 0, 0, 0), gateway, subnet );
+#else
+ WiFi.config( local_ip, gateway, subnet );
+#endif
+ }
+
+ /**
+ * @return local IP address
+ */
+ inline IPAddress getLocalIP()
+ {
+ return WiFi.localIP();
+ }
+
+/******************************************************************************
+ * network functions
+ ******************************************************************************/
+
+ /**
+ * maintain WiFi and TCP connection
+ * @return true if WiFi and TCP connection are established
+ */
+ virtual bool maintain() = 0;
+
+#ifdef ESP8266
+ /**
+ * get status of TCP connection
+ * @return status of TCP connection
+ * CLOSED = 0 (typical)
+ * LISTEN = 1 (not used)
+ * SYN_SENT = 2
+ * SYN_RCVD = 3
+ * ESTABLISHED = 4 (typical)
+ * FIN_WAIT_1 = 5
+ * FIN_WAIT_2 = 6
+ * CLOSE_WAIT = 7
+ * CLOSING = 8
+ * LAST_ACK = 9
+ * TIME_WAIT = 10
+ */
+ inline uint8_t status()
+ {
+ return _client.status();
+ }
+#endif
+
+ /**
+ * close TCP client connection
+ */
+ virtual void stop() = 0;
+
+/******************************************************************************
+ * WiFi configuration
+ ******************************************************************************/
+
+ /**
+ * initialize WiFi without security (open) and initiate client connection
+ * if WiFi connection is already established
+ * @return WL_CONNECTED if WiFi connection is established
+ */
+ inline int begin(char *ssid)
+ {
+ _ssid = ssid;
+
+ WiFi.begin(ssid);
+ int result = WiFi.status();
+ return WiFi.status();
+ }
+
+#ifndef ESP8266
+ /**
+ * initialize WiFi with WEP security and initiate client connection
+ * if WiFi connection is already established
+ * @return WL_CONNECTED if WiFi connection is established
+ */
+ inline int begin(char *ssid, uint8_t key_idx, const char *key)
+ {
+ _ssid = ssid;
+ _key_idx = key_idx;
+ _key = key;
+
+ WiFi.begin( ssid, key_idx, key );
+ return WiFi.status();
+ }
+#endif
+
+ /**
+ * initialize WiFi with WPA-PSK security and initiate client connection
+ * if WiFi connection is already established
+ * @return WL_CONNECTED if WiFi connection is established
+ */
+ inline int begin(char *ssid, const char *passphrase)
+ {
+ _ssid = ssid;
+ _passphrase = passphrase;
+
+ WiFi.begin(ssid, passphrase);
+ return WiFi.status();
+ }
+
+
+/******************************************************************************
+ * stream functions
+ ******************************************************************************/
+
+ inline int available()
+ {
+ return connect_client() ? _client.available() : 0;
+ }
+
+ inline void flush()
+ {
+ if( _client ) _client.flush();
+ }
+
+ inline int peek()
+ {
+ return connect_client() ? _client.peek(): 0;
+ }
+
+ inline int read()
+ {
+ return connect_client() ? _client.read() : -1;
+ }
+
+ inline size_t write(uint8_t byte)
+ {
+ return connect_client() ? _client.write( byte ) : 0;
+ }
+
+};
+
+#endif //WIFI_STREAM_H
--- /dev/null
+#ifndef FIRMATA_DEBUG_H
+#define FIRMATA_DEBUG_H
+
+#ifdef SERIAL_DEBUG
+ #define DEBUG_BEGIN(baud) Serial.begin(baud); while(!Serial) {;}
+ #define DEBUG_PRINTLN(x) Serial.println (x); Serial.flush()
+ #define DEBUG_PRINT(x) Serial.print (x)
+#else
+ #define DEBUG_BEGIN(baud)
+ #define DEBUG_PRINTLN(x)
+ #define DEBUG_PRINT(x)
+#endif
+
+#endif /* FIRMATA_DEBUG_H */
--- /dev/null
+For information on installing libraries, see: http://www.arduino.cc/en/Guide/Libraries
--- /dev/null
+#include <AES.h>
+//#include "./printf.h"
+
+AES aes ;
+
+byte *key = (unsigned char*)"0123456789010123";
+const int size_mesg=256;
+
+
+
+
+
+
+//real iv = iv x2 ex: 01234567 = 0123456701234567
+unsigned long long int my_iv = 36753562;
+
+
+
+
+
+
+
+
+
+
+
+void setup ()
+{
+ Serial.begin (57600) ;
+// printf_begin();
+ delay(500);
+// printf("\n===testng mode\n") ;
+
+ randomSeed(134);
+
+
+
+
+
+// otfly_test () ;
+// otfly_test256 () ;
+}
+
+void loop ()
+{
+ prekey_test () ;
+ delay(2000);
+}
+
+void prekey (int bits)
+{
+ aes.iv_inc();
+ byte iv [N_BLOCK] ;
+
+
+ byte plain[size_mesg];
+ byte cipher [size_mesg] ;
+ byte check [size_mesg] ;
+
+ randomSeed(334);
+ for(int i=0;i<size_mesg;i++) {
+ plain[i]=random(255);
+ }
+
+
+
+
+
+ unsigned long ms = micros ();
+ aes.set_IV(my_iv);
+ aes.get_IV(iv);
+
+ aes.do_aes_encrypt(plain,size_mesg,cipher,key,bits,iv);
+ Serial.print("Encryption took: ");
+ Serial.println(micros() - ms);
+ ms = micros ();
+ aes.set_IV(my_iv);
+ aes.get_IV(iv);
+ aes.do_aes_decrypt(cipher,size_mesg,check,key,bits,iv);
+ Serial.print("Decryption took: ");
+ Serial.println(micros() - ms);
+/* printf("\n\nPLAIN :");
+ aes.printArray(plain,(bool)true);
+ printf("\nCIPHER:");
+ aes.printArray(cipher,(bool)false);
+ printf("\nCHECK :");
+ aes.printArray(check,(bool)true);
+ printf("\nIV :");
+ aes.printArray(iv,16);
+ printf("\n============================================================\n");
+
+ */
+ bool equal=true;
+ for(int i=0;i<size_mesg-1;i++) {
+
+ if(check[i]!=plain[i]) {
+ printf("%d %d %d\n",plain[i],check[i],i);
+ equal=false;
+ }
+ }
+ printf("CHECK %d\n",equal);
+
+}
+
+void prekey_test ()
+{
+ prekey (128) ;
+}
+
--- /dev/null
+#include <AES.h>
+//#include "./printf.h"
+
+AES aes ;
+
+byte *key = (unsigned char*)"0123456789010123";
+const int size_mesg=256;
+
+
+
+
+
+
+//real iv = iv x2 ex: 01234567 = 0123456701234567
+unsigned long long int my_iv = 36753562;
+
+
+
+
+
+
+
+
+
+
+
+void setup ()
+{
+ Serial.begin (57600) ;
+ // printf_begin();
+ delay(500);
+ printf("\n===testng mode\n") ;
+
+ randomSeed(134);
+
+
+
+
+
+// otfly_test () ;
+// otfly_test256 () ;
+}
+
+void loop ()
+{
+ prekey_test () ;
+ delay(2000);
+}
+
+void prekey (int bits)
+{
+ aes.iv_inc();
+ byte iv [N_BLOCK] ;
+
+
+ byte plain[size_mesg];
+ byte cipher [size_mesg] ;
+ byte check [size_mesg] ;
+
+ randomSeed(334);
+ for(int i=0;i<size_mesg;i++) {
+ plain[i]=random(255);
+ }
+
+
+
+ aes.set_IV(my_iv);
+ aes.get_IV(iv);
+
+ unsigned long ms = micros ();
+
+
+ aes.do_aes_encrypt(plain,size_mesg,cipher,key,bits,iv);
+ Serial.print("Encryption took: ");
+ Serial.println(micros() - ms);
+
+ aes.set_IV(my_iv);
+ aes.get_IV(iv);
+
+
+ ms = micros ();
+ aes.do_aes_decrypt(cipher,size_mesg,check,key,bits,iv);
+ Serial.print("Decryption took: ");
+ Serial.println(micros() - ms);
+/* printf("\n\nPLAIN :");
+ aes.printArray(plain,(bool)true);
+ printf("\nCIPHER:");
+ aes.printArray(cipher,(bool)false);
+ printf("\nCHECK :");
+ aes.printArray(check,(bool)true);
+ printf("\nIV :");
+ aes.printArray(iv,16);
+ printf("\n============================================================\n");
+
+ */
+ bool equal=true;
+ for(int i=0;i<size_mesg-1;i++) {
+
+ if(check[i]!=plain[i]) {
+ printf("%d %d %d\n",plain[i],check[i],i);
+ equal=false;
+ }
+ }
+ //printf("CHECK %d\n",equal);
+
+}
+
+void prekey_test ()
+{
+ prekey (128) ;
+}
+
--- /dev/null
+#include <AESLib.h>
+
+//#include <Esp.h>
+
+
+//#include <AES.h>
+//#include "./printf.h"
+
+
+
+
+
+const int size_mesg = 256;
+
+uint8_t key[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+
+
+void printArray(byte *mes, int n) {
+ for (byte i = 0; i < n; i++) {
+ Serial.print(mes[i]);
+ Serial.print(" ");
+ }
+ Serial.println();
+}
+
+
+void setup() {
+ // put your setup code here, to run once:
+ Serial.begin(57600);
+}
+
+void loop() {
+ // put your main code here, to run repeatedly:
+
+ byte plain[size_mesg];
+
+ randomSeed(334);
+ for (int i = 0; i < size_mesg; i++) {
+ plain[i] = random(255);
+ }
+
+ //Serial.print("plain :");
+ // printArray(plain,size_mesg);
+
+
+
+ unsigned long ms1 = micros ();
+ for(int i=0;i<size_mesg;i+=16) {
+ aes128_enc_single(key, &plain[i]);
+ }
+ Serial.print("Encryption took: ");
+ Serial.println(micros() - ms1);
+ //Serial.print("encrypted:");
+ //printArray(plain,size_mesg);
+
+ ms1 = micros ();
+ for(int i=0;i<size_mesg;i+=16) {
+ aes128_dec_single(key, &plain[i]);
+ }
+ Serial.print("Decryption took: ");
+ Serial.println(micros() - ms1);
+ //Serial.print("decrypted:");
+ //printArray(plain,size_mesg);
+
+ delay(2000);
+}
--- /dev/null
+#include <Crypto.h>
+
+
+
+
+int size_mesg=256;
+
+byte *key = (unsigned char*)"0123456789010123";
+byte *iv = (unsigned char*)"0123456789010123";
+
+
+void printArray(byte *mes, int n) {
+ for (byte i = 0; i < n; i++) {
+ Serial.print(mes[i]);
+ Serial.print(" ");
+ }
+ Serial.println();
+}
+
+
+
+void setup() {
+ // put your setup code here to run once:
+ Serial.begin (57600) ;
+// printf_begin();
+ delay(500);
+}
+
+void loop() {
+ // put your main code here, to run repeatedly:
+
+ AES aes(key, iv, AES::AES_MODE_128, AES::CIPHER_ENCRYPT);
+
+ uint8_t plain[size_mesg];
+ uint8_t cipher [size_mesg] ;
+ uint8_t check [size_mesg] ;
+
+
+ randomSeed(334);
+ for(int i=0;i<size_mesg;i++) {
+ plain[i]=random(255);
+ }
+
+
+unsigned long ms1 = micros ();
+ aes.encryptCBC(plain, cipher, size_mesg);
+ Serial.print("Encryption took: ");
+ Serial.println(micros() - ms1);
+AES aes2(key, iv, AES::AES_MODE_128, AES::CIPHER_DECRYPT);
+
+ // aes.convertKey();
+ms1 = micros ();
+ aes2.decryptCBC(cipher, check, size_mesg);
+Serial.print("Decryption took: ");
+ Serial.println(micros() - ms1);
+
+
+
+/*printArray(plain,size_mesg);
+printArray(cipher,size_mesg);
+printArray(check,size_mesg);
+*/
+ bool equal=true;
+ for(int i=0;i<size_mesg-1;i++) {
+
+ if(check[i]!=plain[i]) {
+ // printf("%d %d %d\n",plain[i],check[i],i);
+ equal=false;
+ }
+ }
+ printf("CHECK %d\n",equal);
+
+delay(2000);
+
+}
--- /dev/null
+#include <AES.h>
+//#include "./printf.h"
+
+
+
+//#include <ESP8266WiFi.h>
+
+const int size_mesg=256;
+
+
+
+
+const int sleepTimeS = 10;
+
+
+const int h=4;
+const int h2=h*h;
+byte DK[64];
+int rp=1;
+
+const int len=size_mesg/h2;
+
+
+
+typedef byte uchar;
+
+int Pbox[len];
+ int PboxRM[h2];
+ uchar Sbox1[256];
+ uchar Sbox2[256];
+ uchar RM1_cpy[h2];
+
+
+
+
+
+
+
+
+
+
+void inverse_tables(uchar *tab, int size_tab,uchar *inv_perm_tabs) {
+
+ for(int i=0;i<size_tab;i++) {
+ inv_perm_tabs[tab[i]] = i;
+ }
+
+}
+
+void inverse_tables_int(int *tab, int size_tab,int *inv_perm_tabs) {
+
+ for(int i=0;i<size_tab;i++) {
+ inv_perm_tabs[tab[i]] = i;
+ }
+
+}
+
+
+
+void rc4key(uchar *key, uchar *sc, int size_DK) {
+
+ for(int i=0;i<256;i++) {
+ sc[i]=i;
+ }
+
+
+ uchar j0 = 0;
+ for(int i0=0; i0<256; i0++) {
+ j0 = (j0 + sc[i0] + key[i0%size_DK] )&0xFF;
+ uchar tmp = sc[i0];
+ sc[i0] = sc[j0 ];
+ sc[j0] = tmp;
+ }
+}
+
+
+
+void rc4keyperm(uchar *key,int len, int rp,int *sc, int size_DK) {
+
+ //sc=1:len;
+
+
+
+ for (int i=0;i<len;i++) {
+ sc[i]=i;
+ }
+ for (int it = 0; it < rp; it++) {
+ int j0 = 1;
+ for(int i0 = 0; i0<len; i0++) {
+ j0 = (j0 + sc[i0] + sc[j0] + key[i0%size_DK] )% len;
+ int tmp = sc[i0];
+ sc[i0] = sc[j0];
+ sc[j0] = tmp;
+ }
+
+ }
+}
+
+void prga(uchar *sc, int ldata, uchar *r) {
+ uchar i0=0;
+ uchar j0=0;
+
+ for (int it=0; it<ldata; it++) {
+ i0 = ((i0+1)&0xFE); //%255);
+ j0 = (j0 + sc[i0])&0xFF;
+ uchar tmp = sc[i0];
+ sc[i0] = sc[j0];
+ sc[j0] = tmp;
+ r[it]=sc[(sc[i0]+sc[j0])&0xFF];
+ }
+}
+
+
+
+void encrypt_ctr(const uchar* seq_in, uchar *seq_out, int len,uchar* RM1,const int *Pbox, const int *PboxRM, const uchar *Sbox1, const uchar *Sbox2, int enc) {
+
+ //printArray(seq_out,16);
+ uchar X[h2];
+ uchar fX[h2];
+
+ int ind1,ind2;
+
+
+ for(int a=0;a<h2;a++) {
+ X[a]=Sbox1[a&0xFF]; //Warning according to the size of h2, we can be outsize of Sbox1[a]
+ }
+
+
+ for(int it=0;it<len;it++) {
+ if(enc) {
+ ind1=it*h2;
+ ind2=Pbox[it]*h2;
+ }
+ else {
+ ind2=it*h2;
+ ind1=Pbox[it]*h2;
+ }
+
+
+ for(int a=0;a<h2;a+=4) {
+ X[a]=X[Sbox1[a]];
+ X[a+1]=X[Sbox1[a+1]];
+ X[a+2]=X[Sbox1[a+2]];
+ X[a+3]=X[Sbox1[a+3]];
+ }
+
+ for(int a=0;a<h2;a+=4){
+ fX[a]=X[a];
+ fX[a+1]=X[a+1];
+ fX[a+2]=X[a+2];
+ fX[a+3]=X[a+3];
+ }
+
+
+
+ //printf("fx %d\n",fX[0] );
+
+ /*
+ for(int a=0;a<h2;a+=16) {
+ *(int*)&fX[a]^=it;
+ *(int*)&fX[a+4]^=it;
+ *(int*)&fX[a+8]^=it;
+ *(int*)&fX[a+12]^=it;
+ }
+ */
+
+
+
+
+ for(int a=0;a<h2;a+=4) {
+ fX[a]=fX[a]^RM1[a];
+ fX[a+1]=fX[a+1]^RM1[a+1];
+ fX[a+2]=fX[a+2]^RM1[a+2];
+ fX[a+3]=fX[a+3]^RM1[a+3];
+ }
+
+
+ for(int a=0;a<h2;a+=4) {
+ fX[a]=Sbox2[fX[a]];
+ fX[a+1]=Sbox2[fX[a+1]];
+ fX[a+2]=Sbox2[fX[a+2]];
+ fX[a+3]=Sbox2[fX[a+3]];
+ }
+
+
+
+
+ for(int a=0;a<h2;a+=4) {
+ fX[a]=fX[a]^seq_in[ind2+a];
+ fX[a+1]=fX[a+1]^seq_in[ind2+a+1];
+ fX[a+2]=fX[a+2]^seq_in[ind2+a+2];
+ fX[a+3]=fX[a+3]^seq_in[ind2+a+3];
+ }
+
+
+
+ for(int a=0;a<h2;a+=4) {
+ seq_out[ind1+a]=fX[a];
+ seq_out[ind1+a+1]=fX[a+1];
+ seq_out[ind1+a+2]=fX[a+2];
+ seq_out[ind1+a+3]=fX[a+3];
+ }
+
+ for(int a=0;a<h2;a+=4) {
+ RM1[a]=RM1[PboxRM[a]];
+ RM1[a+1]=RM1[PboxRM[a+1]];
+ RM1[a+2]=RM1[PboxRM[a+2]];
+ RM1[a+3]=RM1[PboxRM[a+3]];
+ }
+
+
+
+ }
+
+// printf("size mes %d\n",size_mesg);
+// printf("len %d\n",len);
+
+
+//printArray(seq_out,16);
+
+}
+
+
+
+void printArray(byte *mes, int n) {
+ for (byte i = 0; i < n; i++) {
+ Serial.print(mes[i]);
+ Serial.print(" ");
+ }
+ Serial.println();
+}
+
+
+void setup ()
+{
+ Serial.begin (57600) ;
+// printf_begin();
+ delay(500);
+ printf("\n===testng mode\n") ;
+
+
+ uchar sc[256];
+
+ uchar RM1[h2];
+ uchar RM2[h2];
+
+ randomSeed(134);
+
+ for(byte i=0;i<64;i++) {
+ DK[i]=random(255);
+ }
+ rc4key(DK, Sbox1, 8);
+
+
+ rc4key(&DK[8], Sbox2, 8);
+
+ rc4key(&DK[16], sc, 16);
+
+
+ prga(sc, h2, RM1);
+
+
+ rc4keyperm(&DK[32], len, rp, Pbox, 16);
+
+
+ rc4keyperm(&DK[48], h2, rp, PboxRM, 16);
+
+ for(int i=0;i<h2;i++){
+ RM2[i]=RM1[i];
+ RM1_cpy[i]=RM1[i];
+ }
+
+ // WiFi.mode( WIFI_OFF );
+
+Serial.println("END OF INIT");
+
+
+
+// otfly_test () ;
+// otfly_test256 () ;
+}
+
+void loop ()
+{
+ prekey_test () ;
+ delay(1000);
+
+// Serial.println("ESP8266 in sleep mode");
+ // ESP.deepSleep(sleepTimeS * 1000000, WAKE_RF_DISABLED );
+ delay(1000);
+// Serial.println("ESP8266 in normal mode");
+}
+
+void prekey (int bits)
+{
+
+
+ byte plain[size_mesg];
+ byte cipher [size_mesg] ;
+ byte check [size_mesg] ;
+
+ randomSeed(334);
+ for(int i=0;i<size_mesg;i++) {
+ plain[i]=random(255);
+ }
+
+ uchar RM1[h2];
+ uchar RM2[h2];
+
+ for(int i=0;i<h2;i++){
+ RM1[i]=RM1_cpy[i];
+ RM2[i]=RM1_cpy[i];
+ }
+
+
+
+
+ unsigned long ms1 = micros ();
+ encrypt_ctr(plain, cipher,len,RM1,Pbox,PboxRM,Sbox1,Sbox2,1);
+ Serial.print("ONE Encryption took: ");
+ Serial.println(micros() - ms1);
+
+ ms1 = micros ();
+ encrypt_ctr(cipher, check,len,RM2,Pbox,PboxRM,Sbox1,Sbox2,0);
+ Serial.print("ONE Decryption took: ");
+ Serial.println(micros() - ms1);
+
+ printf("\n\nPLAIN :");
+ printArray(plain,16*2);
+ printf("\nCIPHER:");
+ printArray(cipher,16*2);
+ printf("\nCHECK :");
+ printArray(check,16*2);
+
+ bool equal=true;
+ for(int i=0;i<size_mesg;i++) {
+
+ if(check[i]!=plain[i]) {
+ equal=false;
+ }
+ }
+ Serial.print("CHECK ");
+ Serial.println(equal);
+
+}
+
+void prekey_test ()
+{
+ prekey (128) ;
+}
+