initial commit

This commit is contained in:
ston1th 2017-11-05 18:30:54 +01:00
commit f3547bf7b8
15 changed files with 1610 additions and 0 deletions

24
LICENSE Normal file
View file

@ -0,0 +1,24 @@
Copyright (C) 2017 Marius Schellenberger
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* The names of the authors and/or contributors may not be used to
endorse or promote products derived from this software without
specific prior written permission.
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 ston1th 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.

1
README.md Normal file
View file

@ -0,0 +1 @@
# Arduino Projects

442
enigma/enigma.ino Normal file
View file

@ -0,0 +1,442 @@
// Copyright (C) 2017 Marius Schellenberger
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <LiquidCrystal_I2C.h>
/* Display
GND (Display) -> GND (Arduino UNO)
VCC (Display) -> 5V (Arduino UNO)
SDA (Display) -> A4 (Arduino UNO)
SCL (Display) -> A5 (Arduino UNO)
*/
// control
#define TRUE 1
#define D8 8
#define D9 9
#define D10 10
#define D11 11
#define D12 12
int b1, b2, b3, b4, b5;
void read_b(void) {
b1 = digitalRead(D12);
b2 = digitalRead(D11);
b3 = digitalRead(D10);
b4 = digitalRead(D9);
b5 = digitalRead(D8);
}
// data
#define ALPHA_MAX 36
char _itoa[ALPHA_MAX];
int _atoi[91];
void cont(void) {
while (digitalRead(D8) != HIGH);
delay(200);
}
void init_itoa(void) {
for (int i = 0; i < 10; i++)
_itoa[i] = (char)48 + i;
for (int i = 10; i < ALPHA_MAX; i++)
_itoa[i] = (char)55 + i;
}
void init_atoi(void) {
int c = 0;
for (int i = 48; i < 58; i++)
_atoi[i] = c++;
for (int i = 65; i < 91; i++)
_atoi[i] = c++;
}
// random
#define CHAR_MAX 256
const unsigned char _r_max = CHAR_MAX - (CHAR_MAX % ALPHA_MAX);
volatile unsigned char _r_sample = 0;
volatile char _r_new = 0;
unsigned char _r = 0;
ISR(WDT_vect) {
_r_sample = TCNT1L;
_r_new = 1;
}
void _r_init(void) {
cli();
MCUSR = 0;
WDTCSR |= _BV(WDCE) | _BV(WDE);
WDTCSR = _BV(WDIE);
sei();
}
char _r_rotl_one(const char v) {
int shift = 1;
if ((shift &= sizeof(v) * 8 - 1) == 0)
return v;
return (v << shift) | (v >> (sizeof(v) * 8 - shift));
}
char _r_char(void) {
char i = 0;
while (TRUE) {
if (_r_new) {
_r_new = 0;
_r = _r_rotl_one(_r);
_r ^= _r_sample;
if (i++ > 7) {
if (_r < _r_max)
return _itoa[_r % ALPHA_MAX];
else
i = 0;
}
}
}
}
// LCD
#define COLS 20
#define ROWS 4
#define WS ' '
#define NULL_CHAR '\0';
LiquidCrystal_I2C lcd(0x27, COLS, ROWS);
void clr_all(void) {
for (int r = 0; r < ROWS; r++)
clr(r);
}
void clr(const int row) {
for (int c = 0; c < COLS; c++) {
lcd.setCursor(c, row);
lcd.print(WS);
}
}
void prntl(const int row, const char *str) {
int len = strlen(str);
for (int i = 0; i < len; i++)
prntc(row, i, str[i]);
while (len < COLS)
prntc(row, len++, WS);
}
void prntlong(int row, const char *str) {
clr_all();
int c = 0;
for (int i = 0; i < strlen(str); i++) {
prntc(row, c++, str[i]);
if (i == (COLS - 1) || i == ((COLS * 2) - 1) || i == ((COLS * 3) - 1)) {
row++;
c = 0;
}
}
}
void prntstr(const int row, const int col, const int len, const char *str) {
for (int i = 0; i < len; i++)
prntc(row, col+i, str[i]);
}
void prntc(const int row, const int col, const char c) {
lcd.setCursor(col, row);
lcd.print(c);
}
void prnti(const int row, const int col, const int i) {
char buf[10];
itoa(i, buf, 10);
prntstr(row, col, strlen(buf), buf);
}
// char ops
char add_ten(char c) {
for (int i = 0; i < 10; i++)
c = add_one(c);
return c;
}
char add_one(const char c) {
int n = (int)c + 1;
if (n == 91)
return '0';
if (n == 64)
return '9';
if (n == 58)
return 'A';
if (n == 47)
return 'Z';
return (char)n;
}
char sub_ten(char c) {
for (int i = 0; i < 10; i++)
c = sub_one(c);
return c;
}
char sub_one(const char c) {
int n = (int)c - 1;
if (n == 91)
return '0';
if (n == 64)
return '9';
if (n == 58)
return 'A';
if (n == 47)
return 'Z';
return (char)n;
}
// crypto
char *keygen(const int len) {
char *key = (char*)malloc(sizeof(char) * (len + 1));
for (int i = 0; i < len; i++)
key[i] = _r_char();
key[len] = NULL_CHAR;
return key;
}
char *encrypt(const char *txt, const char *key) {
int i = 0, c = 0;
int len = strlen(key);
char *enc = (char*)malloc(sizeof(char) * (len + 1));
while (*txt) {
c = _atoi[(int)*txt++] + _atoi[(int)*key++];
if (c > 36) {
c -= 36;
}
enc[i++] = _itoa[c];
}
enc[len] = NULL_CHAR;
return enc;
}
char *decrypt(const char *enc, const char *key) {
int i = 0, c = 0;
int len = strlen(key);
char *txt = (char*)malloc(sizeof(char) * (len + 1));
while (*enc) {
c = _atoi[(int)*enc++] - _atoi[(int)*key++];
if (c < 0) {
c += 36;
}
txt[i++] = _itoa[c];
}
txt[len] = NULL_CHAR;
return txt;
}
void enc_test(void) {
char txt[] = "0ZYX";
char key[] = "EU16";
char *enc = encrypt(txt, key);
clr_all();
prntl(0, "Encrypt Test");
prntl(2, enc);
prntl(3, "ETZ3");
free(enc);
cont();
}
void dec_test(void) {
char enc[] = "KU69";
char key[] = "AJU9";
char *dec = decrypt(enc, key);
clr_all();
prntl(0, "Decrypt Test");
prntl(2, dec);
prntl(3, "ABC0");
free(dec);
cont();
}
char *input(void) {
char p = 0, in = 'A';
int row = 0, col = 0, c = 0;
int len = COLS;
char *buf = (char*)malloc(sizeof(char) * len);
prntc(row, col, in);
while (TRUE) {
read_b();
if (b1 == HIGH) {
delay(100);
if (b2 == HIGH) {
prntc(row, col--, WS);
if (c > 0)
c--;
if (row > 0 && col < 0) {
row--;
col = (COLS - 1);
}
in = 'A';
delay(300);
}
}
if (b3 == HIGH) {
delay(100);
if (b4 == HIGH) {
prntc(row, col, WS);
buf = (char*)realloc(buf, sizeof(char) * c);
buf[c] = NULL_CHAR;
return buf;
}
}
if (b5 == HIGH) {
if (col == COLS || col == (COLS * 2) || col == (COLS * 3)) {
row++;
col = 0;
}
prntc(row, col++, in);
buf[c++] = in;
if (c == len) {
len += COLS;
buf = (char*)realloc(buf, sizeof(char) * len);
}
delay(300);
}
if (b1 == HIGH) {
in = sub_ten(in);
p = 1;
}
if (b2 == HIGH) {
in = sub_one(in);
p = 1;
}
if (b3 == HIGH) {
in = add_one(in);
p = 1;
}
if (b4 == HIGH) {
in = add_ten(in);
p = 1;
}
if (p) {
p = 0;
prntc(row, col, in);
delay(200);
}
}
}
void enc_mode(void) {
clr_all();
char *txt, *key, *enc;
txt = input();
key = keygen(strlen(txt));
enc = encrypt(txt, key);
prntlong(0, key);
cont();
prntlong(0, enc);
free(txt);
free(key);
free(enc);
cont();
}
void dec_mode(void) {
clr_all();
int len = 0;
char *enc, *key, *dec;
enc = input();
clr_all();
key = input();
dec = decrypt(enc, key);
prntlong(0, dec);
free(enc);
free(key);
free(dec);
cont();
}
void key_mode(void) {
clr_all();
char p = 0;
char *key;
int len = COLS * 2;
prnti(0, 0, len);
while (TRUE) {
read_b();
if (b1 == HIGH && len > 10) {
len -= 10;
p = 1;
}
if (b2 == HIGH && len > 1) {
len--;
p = 1;
}
if (b3 == HIGH && len < (COLS * ROWS)) {
len++;
p = 1;
}
if (b4 == HIGH && len <= ((COLS * ROWS) - 10)) {
len += 10;
p = 1;
}
if (p) {
p = 0;
prntl(0, "");
prnti(0, 0, len);
delay(150);
}
if (b5 == HIGH)
break;
}
key = keygen(len);
prntlong(0, key);
free(key);
cont();
}
void setup(void) {
pinMode(D8, INPUT);
pinMode(D9, INPUT);
pinMode(D10, INPUT);
pinMode(D11, INPUT);
pinMode(D12, INPUT);
_r_init();
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
init_atoi();
init_itoa();
}
void loop(void) {
clr_all();
prntl(0, "Encrypt: 1 KeyGen: 5");
prntl(1, "Decrypt: 2");
prntl(2, "Encrypt Test: 3");
prntl(3, "Decrypt Test: 4");
while (TRUE) {
read_b();
if (b1 == HIGH) {
enc_mode();
break;
}
if (b2 == HIGH) {
dec_mode();
break;
}
if (b3 == HIGH) {
enc_test();
break;
}
if (b4 == HIGH) {
dec_test();
break;
}
if (b5 == HIGH) {
key_mode();
break;
}
}
}

View file

@ -0,0 +1,322 @@
#include <Arduino.h>
#include <Entropy.h>
const uint8_t WDT_MAX_8INT=0xFF;
const uint16_t WDT_MAX_16INT=0xFFFF;
const uint32_t WDT_MAX_32INT=0xFFFFFFFF;
// Since the Due TRNG is so fast we don't need a circular buffer for it
#ifndef ARDUINO_SAM_DUE
const uint8_t gWDT_buffer_SIZE=32;
const uint8_t WDT_POOL_SIZE=8;
uint8_t gWDT_buffer[gWDT_buffer_SIZE];
uint8_t gWDT_buffer_position;
uint8_t gWDT_loop_counter;
volatile uint8_t gWDT_pool_start;
volatile uint8_t gWDT_pool_end;
volatile uint8_t gWDT_pool_count;
volatile uint32_t gWDT_entropy_pool[WDT_POOL_SIZE];
#endif
// This function initializes the global variables needed to implement the circular entropy pool and
// the buffer that holds the raw Timer 1 values that are used to create the entropy pool. It then
// Initializes the Watch Dog Timer (WDT) to perform an interrupt every 2048 clock cycles, (about
// 16 ms) which is as fast as it can be set.
void EntropyClass::initialize(void)
{
#ifndef ARDUINO_SAM_DUE
gWDT_buffer_position=0;
gWDT_pool_start = 0;
gWDT_pool_end = 0;
gWDT_pool_count = 0;
#endif
#if defined(__AVR__)
cli(); // Temporarily turn off interrupts, until WDT configured
MCUSR = 0; // Use the MCU status register to reset flags for WDR, BOR, EXTR, and POWR
_WD_CONTROL_REG |= (1<<_WD_CHANGE_BIT) | (1<<WDE);
// WDTCSR |= _BV(WDCE) | _BV(WDE);// WDT control register, This sets the Watchdog Change Enable (WDCE) flag, which is needed to set the
_WD_CONTROL_REG = _BV(WDIE); // Watchdog system reset (WDE) enable and the Watchdog interrupt enable (WDIE)
sei(); // Turn interupts on
#elif defined(ARDUINO_SAM_DUE)
pmc_enable_periph_clk(ID_TRNG);
TRNG->TRNG_IDR = 0xFFFFFFFF;
TRNG->TRNG_CR = TRNG_CR_KEY(0x524e47) | TRNG_CR_ENABLE;
#elif defined(__arm__) && defined(TEENSYDUINO)
SIM_SCGC5 |= SIM_SCGC5_LPTIMER;
LPTMR0_CSR = 0b10000100;
LPTMR0_PSR = 0b00000101; // PCS=01 : 1 kHz clock
LPTMR0_CMR = 0x0006; // smaller number = faster random numbers...
LPTMR0_CSR = 0b01000101;
NVIC_ENABLE_IRQ(IRQ_LPTMR);
#endif
}
// This function returns a uniformly distributed random integer in the range
// of [0,0xFFFFFFFF] as long as some entropy exists in the pool and a 0
// otherwise. To ensure a proper random return the available() function
// should be called first to ensure that entropy exists.
//
// The pool is implemented as an 8 value circular buffer
uint32_t EntropyClass::random(void)
{
#ifdef ARDUINO_SAM_DUE
while (! (TRNG->TRNG_ISR & TRNG_ISR_DATRDY))
;
retVal = TRNG->TRNG_ODATA;
#else
uint8_t waiting;
while (gWDT_pool_count < 1)
waiting += 1;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
retVal = gWDT_entropy_pool[gWDT_pool_start];
gWDT_pool_start = (gWDT_pool_start + 1) % WDT_POOL_SIZE;
--gWDT_pool_count;
}
#endif
return(retVal);
}
// This function returns one byte of a single 32-bit entropy value, while preserving the remaining bytes to
// be returned upon successive calls to the method. This makes best use of the available entropy pool when
// only bytes size chunks of entropy are needed. Not available to public use since there is a method of using
// the default random method for the end-user to achieve the same results. This internal method is for providing
// that capability to the random method, shown below
uint8_t EntropyClass::random8(void)
{
static uint8_t byte_position=0;
uint8_t retVal8;
if (byte_position == 0)
share_entropy.int32 = random();
retVal8 = share_entropy.int8[byte_position++];
byte_position = byte_position % 4;
return(retVal8);
}
// This function returns one word of a single 32-bit entropy value, while preserving the remaining word to
// be returned upon successive calls to the method. This makes best use of the available entropy pool when
// only word sized chunks of entropy are needed. Not available to public use since there is a method of using
// the default random method for the end-user to achieve the same results. This internal method is for providing
// that capability to the random method, shown below
uint16_t EntropyClass::random16(void)
{
static uint8_t word_position=0;
uint16_t retVal16;
if (word_position == 0)
share_entropy.int32 = random();
retVal16 = share_entropy.int16[word_position++];
word_position = word_position % 2;
return(retVal16);
}
uint8_t EntropyClass::randomByte(void)
{
return random8();
}
uint16_t EntropyClass::randomWord(void)
{
return random16();
}
// This function returns a uniformly distributed integer in the range of
// of [0,max). The added complexity of this function is required to ensure
// a uniform distribution since the naive modulus max (% max) introduces
// bias for all values of max that are not powers of two.
//
// The loops below are needed, because there is a small and non-uniform chance
// That the division below will yield an answer = max, so we just get
// the next random value until answer < max. Which prevents the introduction
// of bias caused by the division process. This is why we can't use the
// simpler modulus operation which introduces significant bias for divisors
// that aren't a power of two
uint32_t EntropyClass::random(uint32_t max)
{
uint32_t slice;
if (max < 2)
retVal=0;
else
{
retVal = WDT_MAX_32INT;
if (max <= WDT_MAX_8INT) // If only byte values are needed, make best use of entropy
{ // by diving the long into four bytes and using individually
slice = WDT_MAX_8INT / max;
while (retVal >= max)
retVal = random8() / slice;
}
else if (max <= WDT_MAX_16INT) // If only word values are need, make best use of entropy
{ // by diving the long into two words and using individually
slice = WDT_MAX_16INT / max;
while (retVal >= max)
retVal = random16() / slice;
}
else
{
slice = WDT_MAX_32INT / max;
while (retVal >= max)
retVal = random() / slice;
}
}
return(retVal);
}
// This function returns a uniformly distributed integer in the range of
// of [min,max).
uint32_t EntropyClass::random(uint32_t min, uint32_t max)
{
uint32_t tmp_random, tmax;
tmax = max - min;
if (tmax < 1)
retVal=min;
else
{
tmp_random = random(tmax);
retVal = min + tmp_random;
}
return(retVal);
}
// This function returns a uniformly distributed single precision floating point
// in the range of [0.0,1.0)
float EntropyClass::randomf(void)
{
float fRetVal;
// Since c++ doesn't allow bit manipulations of floating point types, we are
// using integer type and arrange its bit pattern to follow the IEEE754 bit
// pattern for single precision floating point value in the range of 1.0 - 2.0
uint32_t tmp_random = random();
tmp_random = (tmp_random & 0x007FFFFF) | 0x3F800000;
// We then copy that binary representation from the temporary integer to the
// returned floating point value
memcpy((void *) &fRetVal, (void *) &tmp_random, sizeof(fRetVal));
// Now translate the value back to its intended range by subtracting 1.0
fRetVal = fRetVal - 1.0;
return (fRetVal);
}
// This function returns a uniformly distributed single precision floating point
// in the range of [0.0, max)
float EntropyClass::randomf(float max)
{
float fRetVal;
fRetVal = randomf() * max;
return(fRetVal);
}
// This function returns a uniformly distributed single precision floating point
// in the range of [min, max)
float EntropyClass::randomf(float min,float max)
{
float fRetVal;
float tmax;
tmax = max - min;
fRetVal = (randomf() * tmax) + min;
return(fRetVal);
}
// This function implements the Marsaglia polar method of converting a uniformly
// distributed random numbers to a normaly distributed (bell curve) with the
// mean and standard deviation specified. This type of random number is useful
// for a variety of purposes, like Monte Carlo simulations.
float EntropyClass::rnorm(float mean, float stdDev)
{
static float spare;
static float u1;
static float u2;
static float s;
static bool isSpareReady = false;
if (isSpareReady)
{
isSpareReady = false;
return ((spare * stdDev) + mean);
} else {
do {
u1 = (randomf() * 2) - 1;
u2 = (randomf() * 2) - 1;
s = (u1 * u1) + (u2 * u2);
} while (s >= 1.0);
s = sqrt(-2.0 * log(s) / s);
spare = u2 * s;
isSpareReady = true;
return(mean + (stdDev * u1 * s));
}
}
// This function returns a unsigned char (8-bit) with the number of unsigned long values
// in the entropy pool
uint8_t EntropyClass::available(void)
{
#ifdef ARDUINO_SAM_DUE
return(TRNG->TRNG_ISR & TRNG_ISR_DATRDY);
#else
return(gWDT_pool_count);
#endif
}
// Circular buffer is not needed with the speed of the Arduino Due trng hardware generator
#ifndef ARDUINO_SAM_DUE
// This interrupt service routine is called every time the WDT interrupt is triggered.
// With the default configuration that is approximately once every 16ms, producing
// approximately two 32-bit integer values every second.
//
// The pool is implemented as an 8 value circular buffer
static void isr_hardware_neutral(uint8_t val)
{
gWDT_buffer[gWDT_buffer_position] = val;
gWDT_buffer_position++; // every time the WDT interrupt is triggered
if (gWDT_buffer_position >= gWDT_buffer_SIZE)
{
gWDT_pool_end = (gWDT_pool_start + gWDT_pool_count) % WDT_POOL_SIZE;
// The following code is an implementation of Jenkin's one at a time hash
// This hash function has had preliminary testing to verify that it
// produces reasonably uniform random results when using WDT jitter
// on a variety of Arduino platforms
for(gWDT_loop_counter = 0; gWDT_loop_counter < gWDT_buffer_SIZE; ++gWDT_loop_counter)
{
gWDT_entropy_pool[gWDT_pool_end] += gWDT_buffer[gWDT_loop_counter];
gWDT_entropy_pool[gWDT_pool_end] += (gWDT_entropy_pool[gWDT_pool_end] << 10);
gWDT_entropy_pool[gWDT_pool_end] ^= (gWDT_entropy_pool[gWDT_pool_end] >> 6);
}
gWDT_entropy_pool[gWDT_pool_end] += (gWDT_entropy_pool[gWDT_pool_end] << 3);
gWDT_entropy_pool[gWDT_pool_end] ^= (gWDT_entropy_pool[gWDT_pool_end] >> 11);
gWDT_entropy_pool[gWDT_pool_end] += (gWDT_entropy_pool[gWDT_pool_end] << 15);
gWDT_entropy_pool[gWDT_pool_end] = gWDT_entropy_pool[gWDT_pool_end];
gWDT_buffer_position = 0; // Start collecting the next 32 bytes of Timer 1 counts
if (gWDT_pool_count == WDT_POOL_SIZE) // The entropy pool is full
gWDT_pool_start = (gWDT_pool_start + 1) % WDT_POOL_SIZE;
else // Add another unsigned long (32 bits) to the entropy pool
++gWDT_pool_count;
}
}
#endif
#if defined( __AVR_ATtiny25__ ) || defined( __AVR_ATtiny45__ ) || defined( __AVR_ATtiny85__ )
ISR(WDT_vect)
{
isr_hardware_neutral(TCNT0);
}
#elif defined(__AVR__)
ISR(WDT_vect)
{
isr_hardware_neutral(TCNT1L); // Record the Timer 1 low byte (only one needed)
}
#elif defined(__arm__) && defined(TEENSYDUINO)
void lptmr_isr(void)
{
LPTMR0_CSR = 0b10000100;
LPTMR0_CSR = 0b01000101;
isr_hardware_neutral(SYST_CVR);
}
#endif
// The library implements a single global instance. There is no need, nor will the library
// work properly if multiple instances are created.
EntropyClass Entropy;

View file

@ -0,0 +1,55 @@
#ifndef Entropy_h
#define Entropy_h
#include <stdint.h>
// Separate the ARM Due headers we use
#ifdef ARDUINO_SAM_DUE
#include <sam.h>
#include <sam3xa/include/component/component_trng.h>
#endif
// Teensy required headers
#ifdef TEENSYDUINO
#include <util/atomic.h>
#endif
// Separate AVR headers from ARM headers
#ifdef __AVR__
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <util/atomic.h>
#endif
const uint32_t WDT_RETURN_BYTE=256;
const uint32_t WDT_RETURN_WORD=65536;
union ENTROPY_LONG_WORD
{
uint32_t int32;
uint16_t int16[2];
uint8_t int8[4];
};
class EntropyClass
{
public:
void initialize(void);
uint32_t random(void);
uint32_t random(uint32_t max);
uint32_t random(uint32_t min, uint32_t max);
uint8_t randomByte(void);
uint16_t randomWord(void);
float randomf(void);
float randomf(float max);
float randomf(float min, float max);
float rnorm(float mean, float stdDev);
uint8_t available(void);
private:
ENTROPY_LONG_WORD share_entropy;
uint32_t retVal;
uint8_t random8(void);
uint16_t random16(void);
};
extern EntropyClass Entropy;
#endif

View file

@ -0,0 +1,322 @@
//YWROBOT
//last updated on 21/12/2011
//Tim Starling Fix the reset bug (Thanks Tim)
//wiki doc http://www.dfrobot.com/wiki/index.php?title=I2C/TWI_LCD1602_Module_(SKU:_DFR0063)
//Support Forum: http://www.dfrobot.com/forum/
//Compatible with the Arduino IDE 1.0
//Library version:1.1
#include "LiquidCrystal_I2C.h"
#include <inttypes.h>
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#define printIIC(args) Wire.write(args)
inline size_t LiquidCrystal_I2C::write(uint8_t value) {
send(value, Rs);
return 0;
}
#else
#include "WProgram.h"
#define printIIC(args) Wire.send(args)
inline void LiquidCrystal_I2C::write(uint8_t value) {
send(value, Rs);
}
#endif
#include "Wire.h"
// When the display powers up, it is configured as follows:
//
// 1. Display clear
// 2. Function set:
// DL = 1; 8-bit interface data
// N = 0; 1-line display
// F = 0; 5x8 dot character font
// 3. Display on/off control:
// D = 0; Display off
// C = 0; Cursor off
// B = 0; Blinking off
// 4. Entry mode set:
// I/D = 1; Increment by 1
// S = 0; No shift
//
// Note, however, that resetting the Arduino doesn't reset the LCD, so we
// can't assume that its in that state when a sketch starts (and the
// LiquidCrystal constructor is called).
LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows)
{
_Addr = lcd_Addr;
_cols = lcd_cols;
_rows = lcd_rows;
_backlightval = LCD_NOBACKLIGHT;
}
void LiquidCrystal_I2C::init(){
init_priv();
}
void LiquidCrystal_I2C::init_priv()
{
Wire.begin();
_displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
begin(_cols, _rows);
}
void LiquidCrystal_I2C::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {
if (lines > 1) {
_displayfunction |= LCD_2LINE;
}
_numlines = lines;
// for some 1 line displays you can select a 10 pixel high font
if ((dotsize != 0) && (lines == 1)) {
_displayfunction |= LCD_5x10DOTS;
}
// SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
// according to datasheet, we need at least 40ms after power rises above 2.7V
// before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50
delay(50);
// Now we pull both RS and R/W low to begin commands
expanderWrite(_backlightval); // reset expanderand turn backlight off (Bit 8 =1)
delay(1000);
//put the LCD into 4 bit mode
// this is according to the hitachi HD44780 datasheet
// figure 24, pg 46
// we start in 8bit mode, try to set 4 bit mode
write4bits(0x03 << 4);
delayMicroseconds(4500); // wait min 4.1ms
// second try
write4bits(0x03 << 4);
delayMicroseconds(4500); // wait min 4.1ms
// third go!
write4bits(0x03 << 4);
delayMicroseconds(150);
// finally, set to 4-bit interface
write4bits(0x02 << 4);
// set # lines, font size, etc.
command(LCD_FUNCTIONSET | _displayfunction);
// turn the display on with no cursor or blinking default
_displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
display();
// clear it off
clear();
// Initialize to default text direction (for roman languages)
_displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
// set the entry mode
command(LCD_ENTRYMODESET | _displaymode);
home();
}
/********** high level commands, for the user! */
void LiquidCrystal_I2C::clear(){
command(LCD_CLEARDISPLAY);// clear display, set cursor position to zero
delayMicroseconds(2000); // this command takes a long time!
}
void LiquidCrystal_I2C::home(){
command(LCD_RETURNHOME); // set cursor position to zero
delayMicroseconds(2000); // this command takes a long time!
}
void LiquidCrystal_I2C::setCursor(uint8_t col, uint8_t row){
int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
if ( row > _numlines ) {
row = _numlines-1; // we count rows starting w/0
}
command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
}
// Turn the display on/off (quickly)
void LiquidCrystal_I2C::noDisplay() {
_displaycontrol &= ~LCD_DISPLAYON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal_I2C::display() {
_displaycontrol |= LCD_DISPLAYON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
// Turns the underline cursor on/off
void LiquidCrystal_I2C::noCursor() {
_displaycontrol &= ~LCD_CURSORON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal_I2C::cursor() {
_displaycontrol |= LCD_CURSORON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
// Turn on and off the blinking cursor
void LiquidCrystal_I2C::noBlink() {
_displaycontrol &= ~LCD_BLINKON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal_I2C::blink() {
_displaycontrol |= LCD_BLINKON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
// These commands scroll the display without changing the RAM
void LiquidCrystal_I2C::scrollDisplayLeft(void) {
command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
}
void LiquidCrystal_I2C::scrollDisplayRight(void) {
command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
}
// This is for text that flows Left to Right
void LiquidCrystal_I2C::leftToRight(void) {
_displaymode |= LCD_ENTRYLEFT;
command(LCD_ENTRYMODESET | _displaymode);
}
// This is for text that flows Right to Left
void LiquidCrystal_I2C::rightToLeft(void) {
_displaymode &= ~LCD_ENTRYLEFT;
command(LCD_ENTRYMODESET | _displaymode);
}
// This will 'right justify' text from the cursor
void LiquidCrystal_I2C::autoscroll(void) {
_displaymode |= LCD_ENTRYSHIFTINCREMENT;
command(LCD_ENTRYMODESET | _displaymode);
}
// This will 'left justify' text from the cursor
void LiquidCrystal_I2C::noAutoscroll(void) {
_displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
command(LCD_ENTRYMODESET | _displaymode);
}
// Allows us to fill the first 8 CGRAM locations
// with custom characters
void LiquidCrystal_I2C::createChar(uint8_t location, uint8_t charmap[]) {
location &= 0x7; // we only have 8 locations 0-7
command(LCD_SETCGRAMADDR | (location << 3));
for (int i=0; i<8; i++) {
write(charmap[i]);
}
}
// Turn the (optional) backlight off/on
void LiquidCrystal_I2C::noBacklight(void) {
_backlightval=LCD_NOBACKLIGHT;
expanderWrite(0);
}
void LiquidCrystal_I2C::backlight(void) {
_backlightval=LCD_BACKLIGHT;
expanderWrite(0);
}
/*********** mid level commands, for sending data/cmds */
inline void LiquidCrystal_I2C::command(uint8_t value) {
send(value, 0);
}
/************ low level data pushing commands **********/
// write either command or data
void LiquidCrystal_I2C::send(uint8_t value, uint8_t mode) {
uint8_t highnib=value&0xf0;
uint8_t lownib=(value<<4)&0xf0;
write4bits((highnib)|mode);
write4bits((lownib)|mode);
}
void LiquidCrystal_I2C::write4bits(uint8_t value) {
expanderWrite(value);
pulseEnable(value);
}
void LiquidCrystal_I2C::expanderWrite(uint8_t _data){
Wire.beginTransmission(_Addr);
printIIC((int)(_data) | _backlightval);
Wire.endTransmission();
}
void LiquidCrystal_I2C::pulseEnable(uint8_t _data){
expanderWrite(_data | En); // En high
delayMicroseconds(1); // enable pulse must be >450ns
expanderWrite(_data & ~En); // En low
delayMicroseconds(50); // commands need > 37us to settle
}
// Alias functions
void LiquidCrystal_I2C::cursor_on(){
cursor();
}
void LiquidCrystal_I2C::cursor_off(){
noCursor();
}
void LiquidCrystal_I2C::blink_on(){
blink();
}
void LiquidCrystal_I2C::blink_off(){
noBlink();
}
void LiquidCrystal_I2C::load_custom_character(uint8_t char_num, uint8_t *rows){
createChar(char_num, rows);
}
void LiquidCrystal_I2C::setBacklight(uint8_t new_val){
if(new_val){
backlight(); // turn backlight on
}else{
noBacklight(); // turn backlight off
}
}
void LiquidCrystal_I2C::printstr(const char c[]){
//This function is not identical to the function used for "real" I2C displays
//it's here so the user sketch doesn't have to be changed
print(c);
}
// unsupported API functions
void LiquidCrystal_I2C::off(){}
void LiquidCrystal_I2C::on(){}
void LiquidCrystal_I2C::setDelay (int cmdDelay,int charDelay) {}
uint8_t LiquidCrystal_I2C::status(){return 0;}
uint8_t LiquidCrystal_I2C::keypad (){return 0;}
uint8_t LiquidCrystal_I2C::init_bargraph(uint8_t graphtype){return 0;}
void LiquidCrystal_I2C::draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end){}
void LiquidCrystal_I2C::draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_row_end){}
void LiquidCrystal_I2C::setContrast(uint8_t new_val){}

View file

@ -0,0 +1,126 @@
//YWROBOT
#ifndef LiquidCrystal_I2C_h
#define LiquidCrystal_I2C_h
#include <inttypes.h>
#include "Print.h"
#include <Wire.h>
// commands
#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_CURSORSHIFT 0x10
#define LCD_FUNCTIONSET 0x20
#define LCD_SETCGRAMADDR 0x40
#define LCD_SETDDRAMADDR 0x80
// flags for display entry mode
#define LCD_ENTRYRIGHT 0x00
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTINCREMENT 0x01
#define LCD_ENTRYSHIFTDECREMENT 0x00
// flags for display on/off control
#define LCD_DISPLAYON 0x04
#define LCD_DISPLAYOFF 0x00
#define LCD_CURSORON 0x02
#define LCD_CURSOROFF 0x00
#define LCD_BLINKON 0x01
#define LCD_BLINKOFF 0x00
// flags for display/cursor shift
#define LCD_DISPLAYMOVE 0x08
#define LCD_CURSORMOVE 0x00
#define LCD_MOVERIGHT 0x04
#define LCD_MOVELEFT 0x00
// flags for function set
#define LCD_8BITMODE 0x10
#define LCD_4BITMODE 0x00
#define LCD_2LINE 0x08
#define LCD_1LINE 0x00
#define LCD_5x10DOTS 0x04
#define LCD_5x8DOTS 0x00
// flags for backlight control
#define LCD_BACKLIGHT 0x08
#define LCD_NOBACKLIGHT 0x00
#define En B00000100 // Enable bit
#define Rw B00000010 // Read/Write bit
#define Rs B00000001 // Register select bit
class LiquidCrystal_I2C : public Print {
public:
LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows);
void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS );
void clear();
void home();
void noDisplay();
void display();
void noBlink();
void blink();
void noCursor();
void cursor();
void scrollDisplayLeft();
void scrollDisplayRight();
void printLeft();
void printRight();
void leftToRight();
void rightToLeft();
void shiftIncrement();
void shiftDecrement();
void noBacklight();
void backlight();
void autoscroll();
void noAutoscroll();
void createChar(uint8_t, uint8_t[]);
void setCursor(uint8_t, uint8_t);
#if defined(ARDUINO) && ARDUINO >= 100
virtual size_t write(uint8_t);
#else
virtual void write(uint8_t);
#endif
void command(uint8_t);
void init();
////compatibility API function aliases
void blink_on(); // alias for blink()
void blink_off(); // alias for noBlink()
void cursor_on(); // alias for cursor()
void cursor_off(); // alias for noCursor()
void setBacklight(uint8_t new_val); // alias for backlight() and nobacklight()
void load_custom_character(uint8_t char_num, uint8_t *rows); // alias for createChar()
void printstr(const char[]);
////Unsupported API functions (not implemented in this library)
uint8_t status();
void setContrast(uint8_t new_val);
uint8_t keypad();
void setDelay(int,int);
void on();
void off();
uint8_t init_bargraph(uint8_t graphtype);
void draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end);
void draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end);
private:
void init_priv();
void send(uint8_t, uint8_t);
void write4bits(uint8_t);
void expanderWrite(uint8_t);
void pulseEnable(uint8_t);
uint8_t _Addr;
uint8_t _displayfunction;
uint8_t _displaycontrol;
uint8_t _displaymode;
uint8_t _numlines;
uint8_t _cols;
uint8_t _rows;
uint8_t _backlightval;
};
#endif

Binary file not shown.

View file

@ -0,0 +1,69 @@
1,6c1
< //YWROBOT
< //last updated on 26/11/2010
< //Tim Starling Fix the reset bug (Thanks Tim)
< //wiki doc http://www.dfrobot.com/wiki/index.php?title=I2C/TWI_LCD1602_Module_(SKU:_DFR0063)
< //Support Forum: http://www.dfrobot.com/forum/
<
---
> // LiquidCrystal_I2C V2.0
10d4
< #include "WProgram.h"
12c6
<
---
> #include "Arduino.h"
67c61
< delay(50);
---
> delayMicroseconds(50000);
77,90c71,84
< // we start in 8bit mode, try to set 4 bit mode
< write4bits(0x03 << 4);
< delayMicroseconds(4500); // wait min 4.1ms
<
< // second try
< write4bits(0x03 << 4);
< delayMicroseconds(4500); // wait min 4.1ms
<
< // third go!
< write4bits(0x03 << 4);
< delayMicroseconds(150);
<
< // finally, set to 4-bit interface
< write4bits(0x02 << 4);
---
> // we start in 8bit mode, try to set 4 bit mode
> write4bits(0x03);
> delayMicroseconds(4500); // wait min 4.1ms
>
> // second try
> write4bits(0x03);
> delayMicroseconds(4500); // wait min 4.1ms
>
> // third go!
> write4bits(0x03);
> delayMicroseconds(150);
>
> // finally, set to 4-bit interface
> write4bits(0x02);
225c219
< inline void LiquidCrystal_I2C::write(uint8_t value) {
---
> inline size_t LiquidCrystal_I2C::write(uint8_t value) {
226a221
> return 0;
235,238c230,233
< uint8_t highnib=value&0xf0;
< uint8_t lownib=(value<<4)&0xf0;
< write4bits((highnib)|mode);
< write4bits((lownib)|mode);
---
> uint8_t highnib=value>>4;
> uint8_t lownib=value & 0x0F;
> write4bits((highnib)|mode);
> write4bits((lownib)|mode);
248c243
< Wire.send((int)(_data) | _backlightval);
---
> Wire.write((int)(_data) | _backlightval);

View file

@ -0,0 +1,70 @@
//YWROBOT
//Compatible with the Arduino IDE 1.0
//Library version:1.1
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#if defined(ARDUINO) && ARDUINO >= 100
#define printByte(args) write(args);
#else
#define printByte(args) print(args,BYTE);
#endif
uint8_t bell[8] = {0x4,0xe,0xe,0xe,0x1f,0x0,0x4};
uint8_t note[8] = {0x2,0x3,0x2,0xe,0x1e,0xc,0x0};
uint8_t clock[8] = {0x0,0xe,0x15,0x17,0x11,0xe,0x0};
uint8_t heart[8] = {0x0,0xa,0x1f,0x1f,0xe,0x4,0x0};
uint8_t duck[8] = {0x0,0xc,0x1d,0xf,0xf,0x6,0x0};
uint8_t check[8] = {0x0,0x1,0x3,0x16,0x1c,0x8,0x0};
uint8_t cross[8] = {0x0,0x1b,0xe,0x4,0xe,0x1b,0x0};
uint8_t retarrow[8] = { 0x1,0x1,0x5,0x9,0x1f,0x8,0x4};
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display
void setup()
{
lcd.init(); // initialize the lcd
lcd.backlight();
lcd.createChar(0, bell);
lcd.createChar(1, note);
lcd.createChar(2, clock);
lcd.createChar(3, heart);
lcd.createChar(4, duck);
lcd.createChar(5, check);
lcd.createChar(6, cross);
lcd.createChar(7, retarrow);
lcd.home();
lcd.print("Hello world...");
lcd.setCursor(0, 1);
lcd.print(" i ");
lcd.printByte(3);
lcd.print(" arduinos!");
delay(5000);
displayKeyCodes();
}
// display all keycodes
void displayKeyCodes(void) {
uint8_t i = 0;
while (1) {
lcd.clear();
lcd.print("Codes 0x"); lcd.print(i, HEX);
lcd.print("-0x"); lcd.print(i+16, HEX);
lcd.setCursor(0, 1);
for (int j=0; j<16; j++) {
lcd.printByte(i+j);
}
i+=16;
delay(4000);
}
}
void loop()
{
}

View file

@ -0,0 +1,28 @@
//YWROBOT
//Compatible with the Arduino IDE 1.0
//Library version:1.1
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display
void setup()
{
lcd.init(); // initialize the lcd
lcd.init();
// Print a message to the LCD.
lcd.backlight();
lcd.setCursor(3,0);
lcd.print("Hello, world!");
lcd.setCursor(2,1);
lcd.print("Ywrobot Arduino!");
lcd.setCursor(0,2);
lcd.print("Arduino LCM IIC 2004");
lcd.setCursor(2,3);
lcd.print("Power By Ec-yuan!");
}
void loop()
{
}

View file

@ -0,0 +1,34 @@
/*
* Displays text sent over the serial port (e.g. from the Serial Monitor) on
* an attached LCD.
* YWROBOT
*Compatible with the Arduino IDE 1.0
*Library version:1.1
*/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display
void setup()
{
lcd.init(); // initialize the lcd
lcd.backlight();
Serial.begin(9600);
}
void loop()
{
// when characters arrive over the serial port...
if (Serial.available()) {
// wait a bit for the entire message to arrive
delay(100);
// clear the screen
lcd.clear();
// read all the available characters
while (Serial.available() > 0) {
// display each character to the LCD
lcd.write(Serial.read());
}
}
}

View file

@ -0,0 +1,46 @@
###########################################
# Syntax Coloring Map For LiquidCrystal_I2C
###########################################
###########################################
# Datatypes (KEYWORD1)
###########################################
LiquidCrystal_I2C KEYWORD1
###########################################
# Methods and Functions (KEYWORD2)
###########################################
init KEYWORD2
begin KEYWORD2
clear KEYWORD2
home KEYWORD2
noDisplay KEYWORD2
display KEYWORD2
noBlink KEYWORD2
blink KEYWORD2
noCursor KEYWORD2
cursor KEYWORD2
scrollDisplayLeft KEYWORD2
scrollDisplayRight KEYWORD2
leftToRight KEYWORD2
rightToLeft KEYWORD2
shiftIncrement KEYWORD2
shiftDecrement KEYWORD2
noBacklight KEYWORD2
backlight KEYWORD2
autoscroll KEYWORD2
noAutoscroll KEYWORD2
createChar KEYWORD2
setCursor KEYWORD2
print KEYWORD2
blink_on KEYWORD2
blink_off KEYWORD2
cursor_on KEYWORD2
cursor_off KEYWORD2
setBacklight KEYWORD2
load_custom_character KEYWORD2
printstr KEYWORD2
###########################################
# Constants (LITERAL1)
###########################################

1
libraries/readme.txt Normal file
View file

@ -0,0 +1 @@
For information on installing libraries, see: http://www.arduino.cc/en/Guide/Libraries

70
random/random.ino Normal file
View file

@ -0,0 +1,70 @@
// Copyright (C) 2017 Marius Schellenberger
#include <stdint.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
// data
#define ALPHA_MAX 36
char _itoa[ALPHA_MAX];
void init_itoa(void) {
for (int i = 0; i < 10; i++)
_itoa[i] = (char)48 + i;
for (int i = 10; i < ALPHA_MAX; i++)
_itoa[i] = (char)55 + i;
}
// random
#define CHAR_MAX 256
volatile unsigned char _r_sample = 0;
volatile char _r_new = 0;
unsigned char _r = 0;
const unsigned char _r_max = CHAR_MAX - (CHAR_MAX % ALPHA_MAX);
ISR(WDT_vect) {
_r_sample = TCNT1L;
_r_new = 1;
}
void _r_init(void) {
cli();
MCUSR = 0;
WDTCSR |= _BV(WDCE) | _BV(WDE);
WDTCSR = _BV(WDIE);
sei();
}
char _r_rotl_one(const char v) {
int shift = 1;
if ((shift &= sizeof(v) * 8 - 1) == 0)
return v;
return (v << shift) | (v >> (sizeof(v) * 8 - shift));
}
char _r_char(void) {
char i = 0;
while (1) {
if (_r_new) {
_r_new = 0;
_r = _r_rotl_one(_r);
_r ^= _r_sample;
if (i++ > 7) {
if (_r < _r_max)
return _itoa[_r % ALPHA_MAX];
else
i = 0;
}
}
}
}
void setup(void) {
Serial.begin(115200);
_r_init();
init_itoa();
}
void loop(void) {
Serial.write(_r_char());
}