@@ -0,0 +1,5 @@
|
||||
Debug
|
||||
src
|
||||
__vm
|
||||
.vs
|
||||
node_modules
|
||||
@@ -0,0 +1,51 @@
|
||||
#include "Addon.h"
|
||||
#include <Streaming.h>
|
||||
#include <Vector.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
bool Addon::hasFlag(uchar flag)
|
||||
{
|
||||
return TEST(flags, flag);
|
||||
}
|
||||
void Addon::setFlag(uchar flag)
|
||||
{
|
||||
flags = SBI(flags, flag);
|
||||
}
|
||||
void Addon::clearFlag(uchar flag)
|
||||
{
|
||||
CBI(flags, flag);
|
||||
}
|
||||
void Addon::debug(Stream *stream)
|
||||
{
|
||||
|
||||
}
|
||||
void Addon::info(Stream *stream)
|
||||
{
|
||||
|
||||
}
|
||||
void Addon::enable()
|
||||
{
|
||||
this->clearFlag(DISABLED);
|
||||
}
|
||||
void Addon::disable()
|
||||
{
|
||||
this->setFlag(DISABLED);
|
||||
}
|
||||
bool Addon::enabled()
|
||||
{
|
||||
return this->hasFlag(DISABLED);
|
||||
}
|
||||
|
||||
Addon *byId(Addons addons, uchar id)
|
||||
{
|
||||
uchar s = addons.size();
|
||||
for (uchar i = 0; i < s; i++)
|
||||
{
|
||||
Addon *addon = addons[i];
|
||||
if (addon->id == id)
|
||||
{
|
||||
return addon;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
#ifndef ADDON_H
|
||||
#define ADDON_H
|
||||
|
||||
#include <WString.h>
|
||||
#include <Vector.h>
|
||||
|
||||
#include "enums.h"
|
||||
#include "common/macros.h"
|
||||
|
||||
#define ADDON_NORMAL 1 << LOOP | 1 << INFO | 1 << SETUP
|
||||
#ifdef HAS_STATES
|
||||
#define ADDON_STATED ADDON_NORMAL | 1 << STATE
|
||||
#else
|
||||
#define ADDON_STATED ADDON_NORMAL
|
||||
#endif
|
||||
|
||||
class Stream;
|
||||
|
||||
class Addon
|
||||
{
|
||||
|
||||
public:
|
||||
const String name;
|
||||
const short id;
|
||||
millis_t now;
|
||||
millis_t last;
|
||||
millis_t dt;
|
||||
Addon(String _name, short _id) : name(_name),
|
||||
id(_id),
|
||||
now(0),
|
||||
last(0),
|
||||
dt(0)
|
||||
{
|
||||
flags = ADDON_NORMAL;
|
||||
}
|
||||
|
||||
Addon(String _name, short _id, short _flags) : name(_name),
|
||||
id(_id),
|
||||
flags(_flags)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void debug(Stream *stream);
|
||||
virtual void info(Stream *stream);
|
||||
virtual short setup(){};
|
||||
virtual short loop(){};
|
||||
virtual short ok(){};
|
||||
virtual bool pause(){};
|
||||
virtual bool resume(){};
|
||||
virtual bool destroy(){};
|
||||
virtual String state() { return ""; };
|
||||
|
||||
int flags;
|
||||
void setFlag(uchar flag);
|
||||
bool hasFlag(uchar flag);
|
||||
void clearFlag(uchar flag);
|
||||
void enable();
|
||||
void disable();
|
||||
bool enabled();
|
||||
|
||||
#ifdef HAS_ADDON_EEP_STORE
|
||||
void save(void* store);
|
||||
void restore(void* store);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
typedef Vector<Addon *> Addons;
|
||||
Addon *byId(Addons addons, uchar id);
|
||||
typedef short (Addon::*AddonFnPtr)(short);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef MULTI_PID_CONTROLLER_H
|
||||
#define MULTI_PID_CONTROLLER_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Streaming.h>
|
||||
#include "../Addon.h"
|
||||
#include "../config.h"
|
||||
|
||||
#include "./common/macros.h"
|
||||
#include "./common/ppmath.h"
|
||||
|
||||
class Partition;
|
||||
|
||||
class MultiPIDController : public Addon
|
||||
{
|
||||
public:
|
||||
MultiPIDController() : Addon(MPID_CTRL_STR, MPIDCTRL, ADDON_STATED)
|
||||
{
|
||||
this->setFlag(DEBUG);
|
||||
}
|
||||
|
||||
private:
|
||||
Partition *partions[MAX_PARTITIONS];
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef PARTITION_H
|
||||
#define PARTITION_H
|
||||
|
||||
#include <max6675.h>
|
||||
#include "./config.h"
|
||||
#include "./macros.h"
|
||||
#include "./time.h"
|
||||
|
||||
/***
|
||||
* The heating cell
|
||||
*/
|
||||
class Partition
|
||||
{
|
||||
public:
|
||||
ushort state; // type: PARTITION_STATE
|
||||
private:
|
||||
ushort pin; // GPIO
|
||||
ushort id;
|
||||
const char name[124]; // for logging
|
||||
|
||||
// computation memory
|
||||
millis_t last_active;
|
||||
millis_t last_duration;
|
||||
|
||||
Partition* next; // for prio/linking
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Interrupt and PWM utilities for 16 bit Timer1 on ATmega168/328
|
||||
* Original code by Jesse Tane for http://labs.ideo.com August 2008
|
||||
* Modified March 2009 by Jérôme Despatis and Jesse Tane for ATmega328 support
|
||||
* Modified June 2009 by Michael Polli and Jesse Tane to fix a bug in setPeriod() which caused the timer to stop
|
||||
* Modified Oct 2009 by Dan Clemens to work with timer1 of the ATMega1280 or Arduino Mega
|
||||
* Modified April 2012 by Paul Stoffregen
|
||||
* Modified again, June 2014 by Paul Stoffregen
|
||||
* Modified July 2017 by Stoyko Dimitrov - added support for ATTiny85 except for the PWM functionality
|
||||
*
|
||||
* This is free software. You can redistribute it and/or modify it under
|
||||
* the terms of Creative Commons Attribution 3.0 United States License.
|
||||
* To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/us/
|
||||
* or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "TimerOne.h"
|
||||
|
||||
TimerOne Timer1; // preinstatiate
|
||||
|
||||
unsigned short TimerOne::pwmPeriod = 0;
|
||||
unsigned char TimerOne::clockSelectBits = 0;
|
||||
void (*TimerOne::isrCallback)() = TimerOne::isrDefaultUnused;
|
||||
|
||||
// interrupt service routine that wraps a user defined function supplied by attachInterrupt
|
||||
#if defined (__AVR_ATtiny85__)
|
||||
ISR(TIMER1_COMPA_vect)
|
||||
{
|
||||
Timer1.isrCallback();
|
||||
}
|
||||
#elif defined(__AVR__)
|
||||
ISR(TIMER1_OVF_vect)
|
||||
{
|
||||
Timer1.isrCallback();
|
||||
}
|
||||
|
||||
#elif defined(__arm__) && defined(CORE_TEENSY)
|
||||
void ftm1_isr(void)
|
||||
{
|
||||
uint32_t sc = FTM1_SC;
|
||||
#ifdef KINETISL
|
||||
if (sc & 0x80) FTM1_SC = sc;
|
||||
#else
|
||||
if (sc & 0x80) FTM1_SC = sc & 0x7F;
|
||||
#endif
|
||||
Timer1.isrCallback();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void TimerOne::isrDefaultUnused()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,485 @@
|
||||
/*
|
||||
* Interrupt and PWM utilities for 16 bit Timer1 on ATmega168/328
|
||||
* Original code by Jesse Tane for http://labs.ideo.com August 2008
|
||||
* Modified March 2009 by Jérôme Despatis and Jesse Tane for ATmega328 support
|
||||
* Modified June 2009 by Michael Polli and Jesse Tane to fix a bug in setPeriod() which caused the timer to stop
|
||||
* Modified April 2012 by Paul Stoffregen - portable to other AVR chips, use inline functions
|
||||
* Modified again, June 2014 by Paul Stoffregen - support Teensy 3.x & even more AVR chips
|
||||
* Modified July 2017 by Stoyko Dimitrov - added support for ATTiny85 except for the PWM functionality
|
||||
*
|
||||
*
|
||||
* This is free software. You can redistribute it and/or modify it under
|
||||
* the terms of Creative Commons Attribution 3.0 United States License.
|
||||
* To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/us/
|
||||
* or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TimerOne_h_
|
||||
#define TimerOne_h_
|
||||
|
||||
#if defined(ARDUINO) && ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
|
||||
#include "config/known_16bit_timers.h"
|
||||
#if defined (__AVR_ATtiny85__)
|
||||
#define TIMER1_RESOLUTION 256UL // Timer1 is 8 bit
|
||||
#elif defined(__AVR__)
|
||||
#define TIMER1_RESOLUTION 65536UL // Timer1 is 16 bit
|
||||
#else
|
||||
#define TIMER1_RESOLUTION 65536UL // assume 16 bits for non-AVR chips
|
||||
#endif
|
||||
|
||||
// Placing nearly all the code in this .h file allows the functions to be
|
||||
// inlined by the compiler. In the very common case with constant values
|
||||
// the compiler will perform all calculations and simply write constants
|
||||
// to the hardware registers (for example, setPeriod).
|
||||
|
||||
|
||||
class TimerOne
|
||||
{
|
||||
|
||||
#if defined (__AVR_ATtiny85__)
|
||||
public:
|
||||
//****************************
|
||||
// Configuration
|
||||
//****************************
|
||||
void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) {
|
||||
TCCR1 = _BV(CTC1); //clear timer1 when it matches the value in OCR1C
|
||||
TIMSK |= _BV(OCIE1A); //enable interrupt when OCR1A matches the timer value
|
||||
setPeriod(microseconds);
|
||||
}
|
||||
void setPeriod(unsigned long microseconds) __attribute__((always_inline)) {
|
||||
const unsigned long cycles = microseconds * ratio;
|
||||
if (cycles < TIMER1_RESOLUTION) {
|
||||
clockSelectBits = _BV(CS10);
|
||||
pwmPeriod = cycles;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 2UL) {
|
||||
clockSelectBits = _BV(CS11);
|
||||
pwmPeriod = cycles / 2;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 4UL) {
|
||||
clockSelectBits = _BV(CS11) | _BV(CS10);
|
||||
pwmPeriod = cycles / 4;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 8UL) {
|
||||
clockSelectBits = _BV(CS12);
|
||||
pwmPeriod = cycles / 8;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 16UL) {
|
||||
clockSelectBits = _BV(CS12) | _BV(CS10);
|
||||
pwmPeriod = cycles / 16;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 32UL) {
|
||||
clockSelectBits = _BV(CS12) | _BV(CS11);
|
||||
pwmPeriod = cycles / 32;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 64UL) {
|
||||
clockSelectBits = _BV(CS12) | _BV(CS11) | _BV(CS10);
|
||||
pwmPeriod = cycles / 64UL;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 128UL) {
|
||||
clockSelectBits = _BV(CS13);
|
||||
pwmPeriod = cycles / 128;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 256UL) {
|
||||
clockSelectBits = _BV(CS13) | _BV(CS10);
|
||||
pwmPeriod = cycles / 256;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 512UL) {
|
||||
clockSelectBits = _BV(CS13) | _BV(CS11);
|
||||
pwmPeriod = cycles / 512;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 1024UL) {
|
||||
clockSelectBits = _BV(CS13) | _BV(CS11) | _BV(CS10);
|
||||
pwmPeriod = cycles / 1024;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 2048UL) {
|
||||
clockSelectBits = _BV(CS13) | _BV(CS12);
|
||||
pwmPeriod = cycles / 2048;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 4096UL) {
|
||||
clockSelectBits = _BV(CS13) | _BV(CS12) | _BV(CS10);
|
||||
pwmPeriod = cycles / 4096;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 8192UL) {
|
||||
clockSelectBits = _BV(CS13) | _BV(CS12) | _BV(CS11);
|
||||
pwmPeriod = cycles / 8192;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 16384UL) {
|
||||
clockSelectBits = _BV(CS13) | _BV(CS12) | _BV(CS11) | _BV(CS10);
|
||||
pwmPeriod = cycles / 16384;
|
||||
} else {
|
||||
clockSelectBits = _BV(CS13) | _BV(CS12) | _BV(CS11) | _BV(CS10);
|
||||
pwmPeriod = TIMER1_RESOLUTION - 1;
|
||||
}
|
||||
OCR1A = pwmPeriod;
|
||||
OCR1C = pwmPeriod;
|
||||
TCCR1 = _BV(CTC1) | clockSelectBits;
|
||||
}
|
||||
|
||||
//****************************
|
||||
// Run Control
|
||||
//****************************
|
||||
void start() __attribute__((always_inline)) {
|
||||
TCCR1 = 0;
|
||||
TCNT1 = 0;
|
||||
resume();
|
||||
}
|
||||
void stop() __attribute__((always_inline)) {
|
||||
TCCR1 = _BV(CTC1);
|
||||
}
|
||||
void restart() __attribute__((always_inline)) {
|
||||
start();
|
||||
}
|
||||
void resume() __attribute__((always_inline)) {
|
||||
TCCR1 = _BV(CTC1) | clockSelectBits;
|
||||
}
|
||||
|
||||
//****************************
|
||||
// PWM outputs
|
||||
//****************************
|
||||
//Not implemented yet for ATTiny85
|
||||
//TO DO
|
||||
|
||||
//****************************
|
||||
// Interrupt Function
|
||||
//****************************
|
||||
void attachInterrupt(void (*isr)()) __attribute__((always_inline)) {
|
||||
isrCallback = isr;
|
||||
TIMSK |= _BV(OCIE1A);
|
||||
}
|
||||
void attachInterrupt(void (*isr)(), unsigned long microseconds) __attribute__((always_inline)) {
|
||||
if(microseconds > 0) setPeriod(microseconds);
|
||||
attachInterrupt(isr);
|
||||
}
|
||||
void detachInterrupt() __attribute__((always_inline)) {
|
||||
//TIMSK = 0; // Timer 0 and Timer 1 both use TIMSK register so setting it to 0 will override settings for Timer1 as well
|
||||
TIMSK &= ~_BV(OCIE1A);
|
||||
}
|
||||
static void (*isrCallback)();
|
||||
static void isrDefaultUnused();
|
||||
|
||||
private:
|
||||
static unsigned short pwmPeriod;
|
||||
static unsigned char clockSelectBits;
|
||||
static const byte ratio = (F_CPU)/ ( 1000000 );
|
||||
|
||||
#elif defined(__AVR__)
|
||||
public:
|
||||
//****************************
|
||||
// Configuration
|
||||
//****************************
|
||||
void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) {
|
||||
TCCR1B = _BV(WGM13); // set mode as phase and frequency correct pwm, stop the timer
|
||||
TCCR1A = 0; // clear control register A
|
||||
setPeriod(microseconds);
|
||||
}
|
||||
void setPeriod(unsigned long microseconds) __attribute__((always_inline)) {
|
||||
const unsigned long cycles = (F_CPU / 2000000) * microseconds;
|
||||
if (cycles < TIMER1_RESOLUTION) {
|
||||
clockSelectBits = _BV(CS10);
|
||||
pwmPeriod = cycles;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 8) {
|
||||
clockSelectBits = _BV(CS11);
|
||||
pwmPeriod = cycles / 8;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 64) {
|
||||
clockSelectBits = _BV(CS11) | _BV(CS10);
|
||||
pwmPeriod = cycles / 64;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 256) {
|
||||
clockSelectBits = _BV(CS12);
|
||||
pwmPeriod = cycles / 256;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 1024) {
|
||||
clockSelectBits = _BV(CS12) | _BV(CS10);
|
||||
pwmPeriod = cycles / 1024;
|
||||
} else {
|
||||
clockSelectBits = _BV(CS12) | _BV(CS10);
|
||||
pwmPeriod = TIMER1_RESOLUTION - 1;
|
||||
}
|
||||
ICR1 = pwmPeriod;
|
||||
TCCR1B = _BV(WGM13) | clockSelectBits;
|
||||
}
|
||||
|
||||
//****************************
|
||||
// Run Control
|
||||
//****************************
|
||||
void start() __attribute__((always_inline)) {
|
||||
TCCR1B = 0;
|
||||
TCNT1 = 0; // TODO: does this cause an undesired interrupt?
|
||||
resume();
|
||||
}
|
||||
void stop() __attribute__((always_inline)) {
|
||||
TCCR1B = _BV(WGM13);
|
||||
}
|
||||
void restart() __attribute__((always_inline)) {
|
||||
start();
|
||||
}
|
||||
void resume() __attribute__((always_inline)) {
|
||||
TCCR1B = _BV(WGM13) | clockSelectBits;
|
||||
}
|
||||
|
||||
//****************************
|
||||
// PWM outputs
|
||||
//****************************
|
||||
void setPwmDuty(char pin, unsigned int duty) __attribute__((always_inline)) {
|
||||
unsigned long dutyCycle = pwmPeriod;
|
||||
dutyCycle *= duty;
|
||||
dutyCycle >>= 10;
|
||||
if (pin == TIMER1_A_PIN) OCR1A = dutyCycle;
|
||||
#ifdef TIMER1_B_PIN
|
||||
else if (pin == TIMER1_B_PIN) OCR1B = dutyCycle;
|
||||
#endif
|
||||
#ifdef TIMER1_C_PIN
|
||||
else if (pin == TIMER1_C_PIN) OCR1C = dutyCycle;
|
||||
#endif
|
||||
}
|
||||
void pwm(char pin, unsigned int duty) __attribute__((always_inline)) {
|
||||
if (pin == TIMER1_A_PIN) { pinMode(TIMER1_A_PIN, OUTPUT); TCCR1A |= _BV(COM1A1); }
|
||||
#ifdef TIMER1_B_PIN
|
||||
else if (pin == TIMER1_B_PIN) { pinMode(TIMER1_B_PIN, OUTPUT); TCCR1A |= _BV(COM1B1); }
|
||||
#endif
|
||||
#ifdef TIMER1_C_PIN
|
||||
else if (pin == TIMER1_C_PIN) { pinMode(TIMER1_C_PIN, OUTPUT); TCCR1A |= _BV(COM1C1); }
|
||||
#endif
|
||||
setPwmDuty(pin, duty);
|
||||
TCCR1B = _BV(WGM13) | clockSelectBits;
|
||||
}
|
||||
void pwm(char pin, unsigned int duty, unsigned long microseconds) __attribute__((always_inline)) {
|
||||
if (microseconds > 0) setPeriod(microseconds);
|
||||
pwm(pin, duty);
|
||||
}
|
||||
void disablePwm(char pin) __attribute__((always_inline)) {
|
||||
if (pin == TIMER1_A_PIN) TCCR1A &= ~_BV(COM1A1);
|
||||
#ifdef TIMER1_B_PIN
|
||||
else if (pin == TIMER1_B_PIN) TCCR1A &= ~_BV(COM1B1);
|
||||
#endif
|
||||
#ifdef TIMER1_C_PIN
|
||||
else if (pin == TIMER1_C_PIN) TCCR1A &= ~_BV(COM1C1);
|
||||
#endif
|
||||
}
|
||||
|
||||
//****************************
|
||||
// Interrupt Function
|
||||
//****************************
|
||||
void attachInterrupt(void (*isr)()) __attribute__((always_inline)) {
|
||||
isrCallback = isr;
|
||||
TIMSK1 = _BV(TOIE1);
|
||||
}
|
||||
void attachInterrupt(void (*isr)(), unsigned long microseconds) __attribute__((always_inline)) {
|
||||
if(microseconds > 0) setPeriod(microseconds);
|
||||
attachInterrupt(isr);
|
||||
}
|
||||
void detachInterrupt() __attribute__((always_inline)) {
|
||||
TIMSK1 = 0;
|
||||
}
|
||||
static void (*isrCallback)();
|
||||
static void isrDefaultUnused();
|
||||
|
||||
private:
|
||||
// properties
|
||||
static unsigned short pwmPeriod;
|
||||
static unsigned char clockSelectBits;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#elif defined(__arm__) && defined(CORE_TEENSY)
|
||||
|
||||
#if defined(KINETISK)
|
||||
#define F_TIMER F_BUS
|
||||
#elif defined(KINETISL)
|
||||
#define F_TIMER (F_PLL/2)
|
||||
#endif
|
||||
|
||||
public:
|
||||
//****************************
|
||||
// Configuration
|
||||
//****************************
|
||||
void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) {
|
||||
setPeriod(microseconds);
|
||||
}
|
||||
void setPeriod(unsigned long microseconds) __attribute__((always_inline)) {
|
||||
const unsigned long cycles = (F_TIMER / 2000000) * microseconds;
|
||||
// A much faster if-else
|
||||
// This is like a binary serch tree and no more than 3 conditions are evaluated.
|
||||
// I haven't checked if this becomes significantly longer ASM than the simple ladder.
|
||||
// It looks very similar to the ladder tho: same # of if's and else's
|
||||
|
||||
/*
|
||||
// This code does not work properly in all cases :(
|
||||
// https://github.com/PaulStoffregen/TimerOne/issues/17
|
||||
if (cycles < TIMER1_RESOLUTION * 16) {
|
||||
if (cycles < TIMER1_RESOLUTION * 4) {
|
||||
if (cycles < TIMER1_RESOLUTION) {
|
||||
clockSelectBits = 0;
|
||||
pwmPeriod = cycles;
|
||||
}else{
|
||||
clockSelectBits = 1;
|
||||
pwmPeriod = cycles >> 1;
|
||||
}
|
||||
}else{
|
||||
if (cycles < TIMER1_RESOLUTION * 8) {
|
||||
clockSelectBits = 3;
|
||||
pwmPeriod = cycles >> 3;
|
||||
}else{
|
||||
clockSelectBits = 4;
|
||||
pwmPeriod = cycles >> 4;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if (cycles > TIMER1_RESOLUTION * 64) {
|
||||
if (cycles > TIMER1_RESOLUTION * 128) {
|
||||
clockSelectBits = 7;
|
||||
pwmPeriod = TIMER1_RESOLUTION - 1;
|
||||
}else{
|
||||
clockSelectBits = 7;
|
||||
pwmPeriod = cycles >> 7;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (cycles > TIMER1_RESOLUTION * 32) {
|
||||
clockSelectBits = 6;
|
||||
pwmPeriod = cycles >> 6;
|
||||
}else{
|
||||
clockSelectBits = 5;
|
||||
pwmPeriod = cycles >> 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (cycles < TIMER1_RESOLUTION) {
|
||||
clockSelectBits = 0;
|
||||
pwmPeriod = cycles;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 2) {
|
||||
clockSelectBits = 1;
|
||||
pwmPeriod = cycles >> 1;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 4) {
|
||||
clockSelectBits = 2;
|
||||
pwmPeriod = cycles >> 2;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 8) {
|
||||
clockSelectBits = 3;
|
||||
pwmPeriod = cycles >> 3;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 16) {
|
||||
clockSelectBits = 4;
|
||||
pwmPeriod = cycles >> 4;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 32) {
|
||||
clockSelectBits = 5;
|
||||
pwmPeriod = cycles >> 5;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 64) {
|
||||
clockSelectBits = 6;
|
||||
pwmPeriod = cycles >> 6;
|
||||
} else
|
||||
if (cycles < TIMER1_RESOLUTION * 128) {
|
||||
clockSelectBits = 7;
|
||||
pwmPeriod = cycles >> 7;
|
||||
} else {
|
||||
clockSelectBits = 7;
|
||||
pwmPeriod = TIMER1_RESOLUTION - 1;
|
||||
}
|
||||
|
||||
uint32_t sc = FTM1_SC;
|
||||
FTM1_SC = 0;
|
||||
FTM1_MOD = pwmPeriod;
|
||||
FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_CPWMS | clockSelectBits | (sc & FTM_SC_TOIE);
|
||||
}
|
||||
|
||||
//****************************
|
||||
// Run Control
|
||||
//****************************
|
||||
void start() __attribute__((always_inline)) {
|
||||
stop();
|
||||
FTM1_CNT = 0;
|
||||
resume();
|
||||
}
|
||||
void stop() __attribute__((always_inline)) {
|
||||
FTM1_SC = FTM1_SC & (FTM_SC_TOIE | FTM_SC_CPWMS | FTM_SC_PS(7));
|
||||
}
|
||||
void restart() __attribute__((always_inline)) {
|
||||
start();
|
||||
}
|
||||
void resume() __attribute__((always_inline)) {
|
||||
FTM1_SC = (FTM1_SC & (FTM_SC_TOIE | FTM_SC_PS(7))) | FTM_SC_CPWMS | FTM_SC_CLKS(1);
|
||||
}
|
||||
|
||||
//****************************
|
||||
// PWM outputs
|
||||
//****************************
|
||||
void setPwmDuty(char pin, unsigned int duty) __attribute__((always_inline)) {
|
||||
unsigned long dutyCycle = pwmPeriod;
|
||||
dutyCycle *= duty;
|
||||
dutyCycle >>= 10;
|
||||
if (pin == TIMER1_A_PIN) {
|
||||
FTM1_C0V = dutyCycle;
|
||||
} else if (pin == TIMER1_B_PIN) {
|
||||
FTM1_C1V = dutyCycle;
|
||||
}
|
||||
}
|
||||
void pwm(char pin, unsigned int duty) __attribute__((always_inline)) {
|
||||
setPwmDuty(pin, duty);
|
||||
if (pin == TIMER1_A_PIN) {
|
||||
*portConfigRegister(TIMER1_A_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
|
||||
} else if (pin == TIMER1_B_PIN) {
|
||||
*portConfigRegister(TIMER1_B_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
|
||||
}
|
||||
}
|
||||
void pwm(char pin, unsigned int duty, unsigned long microseconds) __attribute__((always_inline)) {
|
||||
if (microseconds > 0) setPeriod(microseconds);
|
||||
pwm(pin, duty);
|
||||
}
|
||||
void disablePwm(char pin) __attribute__((always_inline)) {
|
||||
if (pin == TIMER1_A_PIN) {
|
||||
*portConfigRegister(TIMER1_A_PIN) = 0;
|
||||
} else if (pin == TIMER1_B_PIN) {
|
||||
*portConfigRegister(TIMER1_B_PIN) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//****************************
|
||||
// Interrupt Function
|
||||
//****************************
|
||||
void attachInterrupt(void (*isr)()) __attribute__((always_inline)) {
|
||||
isrCallback = isr;
|
||||
FTM1_SC |= FTM_SC_TOIE;
|
||||
NVIC_ENABLE_IRQ(IRQ_FTM1);
|
||||
}
|
||||
void attachInterrupt(void (*isr)(), unsigned long microseconds) __attribute__((always_inline)) {
|
||||
if(microseconds > 0) setPeriod(microseconds);
|
||||
attachInterrupt(isr);
|
||||
}
|
||||
void detachInterrupt() __attribute__((always_inline)) {
|
||||
FTM1_SC &= ~FTM_SC_TOIE;
|
||||
NVIC_DISABLE_IRQ(IRQ_FTM1);
|
||||
}
|
||||
static void (*isrCallback)();
|
||||
static void isrDefaultUnused();
|
||||
|
||||
private:
|
||||
// properties
|
||||
static unsigned short pwmPeriod;
|
||||
static unsigned char clockSelectBits;
|
||||
|
||||
#undef F_TIMER
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
extern TimerOne Timer1;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef VERSION_H
|
||||
|
||||
#define VERSION_H
|
||||
|
||||
#define VERSION "0.7|2f05843f89b2b8f6d75276ba363f7c2e17383e0b"
|
||||
|
||||
#define CID "47"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,59 @@
|
||||
#ifndef CURRENT_SENSOR_H
|
||||
#define CURRENT_SENSOR_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Streaming.h>
|
||||
#include "../Addon.h"
|
||||
#include "../config.h"
|
||||
|
||||
#include "../common/macros.h"
|
||||
#include "../common/ppmath.h"
|
||||
|
||||
class CurrentSensor : public Addon
|
||||
{
|
||||
public:
|
||||
CurrentSensor(short _pin) : pin(_pin),
|
||||
load(0),
|
||||
Addon(CURRENT_SENSOR_STR, CURRENT_SENSOR)
|
||||
{
|
||||
// this->setFlag(DEBUG);
|
||||
}
|
||||
|
||||
short setup()
|
||||
{
|
||||
pinMode(pin, INPUT);
|
||||
loop();
|
||||
}
|
||||
|
||||
short loop()
|
||||
{
|
||||
if (now - last > MOTOR_LOAD_READ_INTERVAL)
|
||||
{
|
||||
load = digitalRead(pin);
|
||||
last = now;
|
||||
}
|
||||
return load;
|
||||
}
|
||||
|
||||
short ok()
|
||||
{
|
||||
return !load;
|
||||
}
|
||||
|
||||
void debug(Stream *stream)
|
||||
{
|
||||
*stream << this->name << ":" << ok();
|
||||
}
|
||||
|
||||
void info(Stream *stream)
|
||||
{
|
||||
*stream << this->name << "\n\t : " SPACE("Pin:" << pin);
|
||||
}
|
||||
|
||||
millis_t lastOverload;
|
||||
|
||||
protected:
|
||||
short pin;
|
||||
short load;
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,56 @@
|
||||
#ifndef DIRECTION_SWITCH_H
|
||||
#define DIRECTION_SWITCH_H
|
||||
|
||||
#include "../config.h"
|
||||
#include "../components/3PosAnalog.h"
|
||||
#include "../Addon.h"
|
||||
#include <Streaming.h>
|
||||
#include "../common/macros.h"
|
||||
|
||||
class DirectionSwitch : public Addon
|
||||
{
|
||||
public:
|
||||
Pos3Analog dir_switch;
|
||||
DirectionSwitch() : dir_switch(DIR_SWITCH_UP_PIN, DIR_SWITCH_DOWN_PIN),
|
||||
Addon(DIRECTION_SWITCH_STR, DIRECTION_SWITCH)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void debug(Stream *stream)
|
||||
{
|
||||
*stream << this->name << ":" << SPACE(dir_switch.switch_pos) << SPACE(dir_switch.last_switch);
|
||||
}
|
||||
void info(Stream *stream)
|
||||
{
|
||||
*stream << this->name << "\n\t : " SPACE("Up Pin:" << DIR_SWITCH_UP_PIN) << SPACE("\t | Down Pin :" << DIR_SWITCH_DOWN_PIN);
|
||||
}
|
||||
short setup()
|
||||
{
|
||||
dir_switch.setup();
|
||||
return loop();
|
||||
}
|
||||
short loop()
|
||||
{
|
||||
if (now - dt > ANALOG_READ_INTERVAL)
|
||||
{
|
||||
_value = dir_switch.loop();
|
||||
dt = now;
|
||||
}
|
||||
return _value;
|
||||
}
|
||||
short value()
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
short last()
|
||||
{
|
||||
return dir_switch.last_switch;
|
||||
}
|
||||
|
||||
private:
|
||||
short _value;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,40 @@
|
||||
#ifndef MOTOR_TEMPERATURE_H
|
||||
#define MOTOR_TEMPERATURE_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "Addon.h"
|
||||
#include "config.h"
|
||||
#include <Streaming.h>
|
||||
#include "../common/macros.h"
|
||||
#include "TemperatureSensor.h"
|
||||
|
||||
class MotorTemperature : public Addon
|
||||
{
|
||||
private:
|
||||
TemperatureSensor sensor;
|
||||
|
||||
public:
|
||||
MotorTemperature() : sensor(MOTOR_TEMPERTURE_SCK_PIN, MOTOR_TEMPERTURE_CS_PIN, MOTOR_TEMPERTURE_SO_PIN, MOTOR_TEMPERTURE_MAX, MOTOR_TEMPERTURE_INTERVAL),
|
||||
Addon(MOTOR_TEMPERATURE_STR, MOTOR_TEMPERATURE) {}
|
||||
|
||||
virtual short ok()
|
||||
{
|
||||
return sensor.ok();
|
||||
}
|
||||
void debug(Stream *stream)
|
||||
{
|
||||
// *stream << this->name << ":" << this->ok();
|
||||
}
|
||||
void info(Stream *stream)
|
||||
{
|
||||
/*
|
||||
*stream << this->name << "\n\t : " <<
|
||||
SPACE("Pin SCK:" << MOTOR_TEMPERTURE_SCK_PIN ) <<
|
||||
SPACE("Pin CS :" << MOTOR_TEMPERTURE_CS_PIN ) <<
|
||||
SPACE("Pin SO:" << MOTOR_TEMPERTURE_SO_PIN ) <<
|
||||
SPACE("Max" << MOTOR_TEMPERTURE_MAX ) <<
|
||||
SPACE("Interval" << MOTOR_TEMPERTURE_INTERVAL );
|
||||
*/
|
||||
}
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,148 @@
|
||||
#ifndef OPERATION_MODE_SWITCH_H
|
||||
#define OPERATION_MODE_SWITCH_H
|
||||
|
||||
#ifdef HAS_STATES
|
||||
#include <ArduinoJson.h>
|
||||
#endif
|
||||
|
||||
#ifndef OP_MODE_ANALOG
|
||||
#include <Bounce2.h>
|
||||
#endif
|
||||
|
||||
#include "../config.h"
|
||||
#include "../Addon.h"
|
||||
#include <Streaming.h>
|
||||
#include "../common/macros.h"
|
||||
#include "../common/ppmath.h"
|
||||
|
||||
class OperationModeSwitch : public Addon
|
||||
{
|
||||
|
||||
public:
|
||||
short pin1;
|
||||
#ifdef OP_MODE_ANALOG
|
||||
ushort level1;
|
||||
ushort level2;
|
||||
ushort level3;
|
||||
OperationModeSwitch(short _pin1, ushort _level1, ushort _level2, ushort _level3) : pin1(_pin1),
|
||||
level1(_level1),
|
||||
level2(_level2),
|
||||
level3(_level3),
|
||||
Addon(OPERATION_MODE_SWITCH_STR, OPERATION_MODE_SWITCH)
|
||||
{
|
||||
//setFlag(DEBUG);
|
||||
}
|
||||
#ifdef HAS_STATES
|
||||
String state()
|
||||
{
|
||||
const int capacity = JSON_OBJECT_SIZE(2);
|
||||
StaticJsonDocument<capacity> doc;
|
||||
doc['0'] = id;
|
||||
doc['1'] = value();
|
||||
return doc.as<String>();
|
||||
}
|
||||
#endif
|
||||
void debug(Stream *stream)
|
||||
{
|
||||
//*stream << this->name << SPACE(value());
|
||||
}
|
||||
void info(Stream *stream)
|
||||
{
|
||||
//*stream << this->name << "\n\t ";
|
||||
}
|
||||
|
||||
short value()
|
||||
{
|
||||
ushort value = analogRead(pin1);
|
||||
if (RANGE(value, level1 - 10, level1 + 10))
|
||||
{
|
||||
return OP_DEBUG;
|
||||
}
|
||||
if (RANGE(value, level2 - 10, level2 + 10))
|
||||
{
|
||||
return OP_NORMAL;
|
||||
}
|
||||
if (RANGE(value, level3 - 10, level3 + 10))
|
||||
{
|
||||
return OP_SERVICE;
|
||||
}
|
||||
return OP_NONE;
|
||||
}
|
||||
short setup()
|
||||
{
|
||||
}
|
||||
|
||||
short loop()
|
||||
{
|
||||
// Serial.println(analogRead(pin1));
|
||||
}
|
||||
|
||||
#else
|
||||
Bounce debouncer1;
|
||||
Bounce debouncer2;
|
||||
Bounce debouncer3;
|
||||
short pin1;
|
||||
short pin2;
|
||||
short pin3;
|
||||
|
||||
OperationModeSwitch(short _pin1, short _pin2, short _pin3) : pin1(_pin1), // 1-2
|
||||
pin2(_pin2), // 5-6
|
||||
pin3(_pin3), // 9-10
|
||||
Addon(OPERATION_MODE_SWITCH_STR, OPERATION_MODE_SWITCH)
|
||||
{
|
||||
}
|
||||
|
||||
void debug(Stream *stream)
|
||||
{
|
||||
*stream << this->name << ": PIN1 " << SPACE(!debouncer1.read()) << ": PIN2 " << SPACE(!debouncer2.read()) << ": PIN3 " << SPACE(!debouncer3.read());
|
||||
}
|
||||
void info(Stream *stream)
|
||||
{
|
||||
*stream << this->name << "\n\t : ";
|
||||
}
|
||||
|
||||
short value()
|
||||
{
|
||||
if (!debouncer1.read())
|
||||
{
|
||||
return OP_DEBUG;
|
||||
}
|
||||
|
||||
if (!debouncer2.read())
|
||||
{
|
||||
return OP_NORMAL;
|
||||
}
|
||||
|
||||
if (!debouncer3.read())
|
||||
{
|
||||
return OP_SERVICE;
|
||||
}
|
||||
|
||||
return OP_NONE;
|
||||
}
|
||||
short setup()
|
||||
{
|
||||
this->debouncer1 = Bounce();
|
||||
this->debouncer1.attach(this->pin1, INPUT_PULLUP);
|
||||
this->debouncer1.interval(25);
|
||||
|
||||
this->debouncer2 = Bounce();
|
||||
this->debouncer2.attach(this->pin2, INPUT_PULLUP);
|
||||
this->debouncer2.interval(25);
|
||||
|
||||
this->debouncer3 = Bounce();
|
||||
this->debouncer3.attach(this->pin3, INPUT_PULLUP);
|
||||
this->debouncer3.interval(25);
|
||||
}
|
||||
|
||||
short loop()
|
||||
{
|
||||
this->debouncer1.update();
|
||||
this->debouncer2.update();
|
||||
this->debouncer3.update();
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef RESET_H
|
||||
#define RESET_H
|
||||
|
||||
// This module uses currently a normally closed momentary button.
|
||||
|
||||
static millis_t sw_reset_TS = 0;
|
||||
|
||||
static void reset_setup()
|
||||
{
|
||||
pinMode(RESET_PIN, INPUT_PULLUP);
|
||||
sw_reset_TS = millis();
|
||||
}
|
||||
|
||||
static void reset_loop()
|
||||
{
|
||||
if (millis() - sw_reset_TS > RESET_INTERVAL) {
|
||||
#if RESET_NC == true
|
||||
// globals.isReset = digitalRead(RESET_PIN);
|
||||
#else
|
||||
// globals.isReset = !digitalRead(RESET_PIN);
|
||||
#endif
|
||||
|
||||
sw_reset_TS = millis();
|
||||
// if(globals.isReset && DEBUG){
|
||||
// Serial.println("reset");
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,110 @@
|
||||
#ifndef STATUS_H
|
||||
#define STATUS_H
|
||||
|
||||
#include "../addon.h"
|
||||
#include "../types.h"
|
||||
#include "../common/macros.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
class Status : public Addon
|
||||
{
|
||||
public:
|
||||
Status(short _errorPin, short _okPin) : errorPin(_errorPin),
|
||||
okPin(_okPin),
|
||||
status_blink_TS(0),
|
||||
doBlink(false),
|
||||
last_blink(true),
|
||||
blink_start_ts(0),
|
||||
max_blink_time(HOUR_MS),
|
||||
Addon(STATUS_STR, STATUS)
|
||||
{
|
||||
}
|
||||
|
||||
short setup()
|
||||
{
|
||||
pinMode(okPin, OUTPUT);
|
||||
pinMode(errorPin, OUTPUT);
|
||||
}
|
||||
|
||||
short loop()
|
||||
{
|
||||
if (now - status_blink_TS > 1000)
|
||||
{
|
||||
status_blink_TS = millis();
|
||||
last_blink = !last_blink;
|
||||
if (doBlink)
|
||||
{
|
||||
digitalWrite(errorPin, last_blink);
|
||||
}
|
||||
|
||||
if (now - blink_start_ts > max_blink_time)
|
||||
{
|
||||
doBlink = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
void status_blink(bool blink)
|
||||
{
|
||||
if (!doBlink && blink)
|
||||
{
|
||||
blink_start_ts = millis();
|
||||
}
|
||||
doBlink = blink;
|
||||
}
|
||||
|
||||
void setStatusAllOn()
|
||||
{
|
||||
if (doBlink)
|
||||
{
|
||||
return;
|
||||
}
|
||||
digitalWrite(errorPin, HIGH);
|
||||
digitalWrite(okPin, HIGH);
|
||||
}
|
||||
|
||||
void setStatusAllOff()
|
||||
{
|
||||
if (doBlink)
|
||||
{
|
||||
return;
|
||||
}
|
||||
digitalWrite(errorPin, LOW);
|
||||
digitalWrite(okPin, LOW);
|
||||
}
|
||||
|
||||
void setStatus(bool error)
|
||||
{
|
||||
if (doBlink)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (error)
|
||||
{
|
||||
digitalWrite(errorPin, HIGH);
|
||||
digitalWrite(okPin, LOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
digitalWrite(okPin, HIGH);
|
||||
digitalWrite(errorPin, LOW);
|
||||
}
|
||||
}
|
||||
|
||||
void info(Stream *stream)
|
||||
{
|
||||
*stream << this->name << "\n\t : " SPACE("Error Pin:" << errorPin) << SPACE("\t | Ok Pin :" << okPin);
|
||||
}
|
||||
|
||||
private:
|
||||
millis_t status_blink_TS;
|
||||
bool doBlink;
|
||||
bool last_blink;
|
||||
millis_t blink_start_ts;
|
||||
millis_t max_blink_time;
|
||||
|
||||
short okPin;
|
||||
short errorPin;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
#ifndef TEMPERATURE_SENSOR_H
|
||||
#define TEMPERATURE_SENSOR_H
|
||||
|
||||
#include <max6675.h>
|
||||
#include "../config.h"
|
||||
#include "../macros.h"
|
||||
#include "../time.h"
|
||||
|
||||
class TemperatureSensor
|
||||
{
|
||||
|
||||
public:
|
||||
TemperatureSensor(short sck, short cs, short so, short _max, short _interval) : ktc(MAX6675(sck, cs, so)),
|
||||
temperature(),
|
||||
temperature_TS(millis()),
|
||||
maxTemp(_max),
|
||||
interval(_interval) {}
|
||||
|
||||
bool ok()
|
||||
{
|
||||
return temperature < maxTemp;
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
if (millis() - temperature_TS > interval)
|
||||
{
|
||||
temperature_TS = millis();
|
||||
temperature = ktc.readCelsius();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
MAX6675 ktc;
|
||||
short temperature;
|
||||
short maxTemp;
|
||||
short interval;
|
||||
millis_t temperature_TS;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,192 @@
|
||||
#include <Vector.h>
|
||||
#include <Streaming.h>
|
||||
#include <Arduino.h>
|
||||
#include "app.h"
|
||||
#include "features.h"
|
||||
#include <MemoryFree.h>
|
||||
#include "Version.h"
|
||||
|
||||
// #define DEBUG_MEM
|
||||
|
||||
static Addon *addonsArray[10];
|
||||
|
||||
#ifdef HAS_STATES
|
||||
short App::appState(short nop)
|
||||
{
|
||||
uchar s = addons.size();
|
||||
uchar si = 0;
|
||||
String out = "";
|
||||
uchar l = numByFlag(STATE);
|
||||
for (uchar i = 0; i < s; i++)
|
||||
{
|
||||
Addon *addon = addons[i];
|
||||
if (!!(addon->hasFlag(STATE)))
|
||||
{
|
||||
si++;
|
||||
out += addon->state();
|
||||
if (si < l)
|
||||
{
|
||||
out += ",";
|
||||
}
|
||||
}
|
||||
}
|
||||
const char *response = Bridge::CreateResponse(STATE_RESPONSE_CODE, 0, out.c_str());
|
||||
Serial.write(response);
|
||||
}
|
||||
#endif
|
||||
|
||||
short App::ok()
|
||||
{
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
App::App() : Addon("APP", APP, 1 << STATE),
|
||||
#ifdef HAS_STATUS
|
||||
status(new Status(STATUS_ERROR_PIN, STATUS_OK_PIN)),
|
||||
#endif
|
||||
cSensor(new CurrentSensor(CURRENT_SENSOR_PIN))
|
||||
{
|
||||
}
|
||||
|
||||
short App::getAppState(short val)
|
||||
{
|
||||
return _state;
|
||||
}
|
||||
void (*resetFunction)(void) = 0; // Self reset (to be used with watchdog)
|
||||
|
||||
void printMem()
|
||||
{
|
||||
Serial.print("mem: ");
|
||||
Serial.print(freeMemory());
|
||||
Serial.println('--');
|
||||
}
|
||||
short App::setup()
|
||||
{
|
||||
Serial.begin(DEBUG_BAUD_RATE);
|
||||
Serial.print("Booting Firmware ...................... \n\n");
|
||||
Serial.print(FIRMWARE_VERSION);
|
||||
Serial.print(" | ");
|
||||
Serial.print(VERSION);
|
||||
Serial.print(" | ");
|
||||
Serial.print(CID);
|
||||
Serial.println(" - \n");
|
||||
addons.setStorage(addonsArray);
|
||||
setup_addons();
|
||||
|
||||
#ifdef MEARSURE_PERFORMANCE
|
||||
printPerfTS = 0;
|
||||
addonLoopTime = 0;
|
||||
bridgeLoopTime = 0;
|
||||
#endif
|
||||
debugTS = 0;
|
||||
loopTS = 0;
|
||||
_state = 0;
|
||||
#ifdef DEBUG_MEM
|
||||
timer.every(
|
||||
5000, [](App *app) -> void {
|
||||
printMem();
|
||||
},
|
||||
this);
|
||||
#endif
|
||||
}
|
||||
|
||||
void App::onError(int error)
|
||||
{
|
||||
if (_state != ERROR)
|
||||
{
|
||||
#ifdef HAS_STATUS
|
||||
status->status_blink(true);
|
||||
#endif
|
||||
|
||||
_state = ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
short App::loop()
|
||||
{
|
||||
timer.tick();
|
||||
now = millis();
|
||||
loop_addons();
|
||||
loop_com();
|
||||
loop_pid();
|
||||
delay(LOOP_DELAY);
|
||||
}
|
||||
|
||||
void App::loop_com()
|
||||
{
|
||||
if (millis() - comTS > 300)
|
||||
{
|
||||
#if defined(HAS_BRIDGE) && defined(HAS_SERIAL)
|
||||
PPSerial::Message *msg = serialBridge->read();
|
||||
if (msg)
|
||||
{
|
||||
switch (msg->verb)
|
||||
{
|
||||
|
||||
case Bridge::EC_METHOD:
|
||||
{
|
||||
char *strings[3];
|
||||
char *ptr = NULL;
|
||||
byte index = 0;
|
||||
|
||||
ptr = strtok(msg->payload, ":");
|
||||
|
||||
while (ptr != NULL && index < 4)
|
||||
{
|
||||
strings[index] = ptr;
|
||||
index++;
|
||||
ptr = strtok(NULL, ":");
|
||||
}
|
||||
|
||||
int id = atoi(strings[0]);
|
||||
char *_method = strings[1];
|
||||
|
||||
SKeyVal *method = VSL::instance()->hasMethod(id, _method);
|
||||
if (method)
|
||||
{
|
||||
int arg = atoi(strings[2]);
|
||||
Addon *addon = (Addon *)method->instance;
|
||||
AddonFnPtr ptr = method->mPtr;
|
||||
short ret = (addon->*ptr)(arg);
|
||||
|
||||
if (TEST(msg->flags, Bridge::STATE))
|
||||
{
|
||||
#ifdef HAS_STATES
|
||||
this->appState(0);
|
||||
#endif
|
||||
}
|
||||
else if (TEST(msg->flags, Bridge::RECEIPT))
|
||||
{
|
||||
#ifdef BRIDGE_HAS_RESPONSE
|
||||
const char *response = Bridge::CreateResponse(msg->id, 0, ret);
|
||||
Serial.write(response);
|
||||
#endif
|
||||
}
|
||||
if (TEST(msg->flags, Bridge::DEBUG))
|
||||
{
|
||||
// Serial.println("Called command");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
VSL::instance()->debug();
|
||||
if (TEST(msg->flags, Bridge::DEBUG))
|
||||
{
|
||||
/*
|
||||
Serial.print("Incoming message, cant find class & method ");
|
||||
Serial.print(_class);
|
||||
Serial.print(":");
|
||||
Serial.print(_method);
|
||||
Serial.print("\n");
|
||||
*/
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
msg->payload = NULL;
|
||||
}
|
||||
#endif
|
||||
comTS = millis();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
#ifndef APP_H
|
||||
#define APP_H
|
||||
|
||||
#include "config.h"
|
||||
#include <Vector.h>
|
||||
#include "types.h"
|
||||
#include "Addon.h"
|
||||
#include "common/timer.h"
|
||||
|
||||
class DirectionSwitch;
|
||||
class CurrentSensor;
|
||||
class Status;
|
||||
class PPSerial;
|
||||
class ModbusBridge;
|
||||
|
||||
class App : public Addon
|
||||
{
|
||||
|
||||
public:
|
||||
App();
|
||||
|
||||
DirectionSwitch *dirSwitch;
|
||||
CurrentSensor *cSensor;
|
||||
Status *status;
|
||||
|
||||
PPSerial *serialBridge;
|
||||
ModbusBridge *modbusBridge;
|
||||
|
||||
Addon *byId(short id);
|
||||
|
||||
short setup();
|
||||
short loop();
|
||||
short debug();
|
||||
short info();
|
||||
short ok();
|
||||
|
||||
void loop_service();
|
||||
void loop_com();
|
||||
void loop_simulate();
|
||||
void loop_pid();
|
||||
void loop_addons();
|
||||
void setup_addons();
|
||||
void onDidSetupAddons();
|
||||
|
||||
ushort numByFlag(ushort flag);
|
||||
short shred(short value = 0);
|
||||
ushort loopShred();
|
||||
void loopShredCancel();
|
||||
|
||||
void onError(int error);
|
||||
|
||||
Vector<Addon *> addons;
|
||||
|
||||
// bridge
|
||||
short setFlag(ushort addonId, ushort flag);
|
||||
|
||||
#ifdef HAS_STATES
|
||||
short appState(short nop = 0);
|
||||
String state();
|
||||
#endif
|
||||
|
||||
millis_t loopTS;
|
||||
millis_t wait;
|
||||
millis_t comTS;
|
||||
millis_t waitTS;
|
||||
Timer<10, millis> timer; // 10 concurrent tasks, using micros as resolution
|
||||
|
||||
enum APP_STATE
|
||||
{
|
||||
RESET = 0,
|
||||
REMOTE = 2,
|
||||
LOCAL = 3,
|
||||
TEST = 3,
|
||||
ERROR = 5
|
||||
};
|
||||
|
||||
short _state;
|
||||
short _error;
|
||||
short getLastError(short val = 0){
|
||||
return _error;
|
||||
}
|
||||
short setLastError(short val = 0);
|
||||
short setAppState(short newState);
|
||||
short getAppState(short val);
|
||||
|
||||
private:
|
||||
|
||||
#ifdef MEARSURE_PERFORMANCE
|
||||
millis_t addonLoopTime;
|
||||
millis_t bridgeLoopTime;
|
||||
millis_t printPerfTS;
|
||||
#endif
|
||||
|
||||
millis_t debugTS;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,150 @@
|
||||
#include <Vector.h>
|
||||
#include <Streaming.h>
|
||||
#include <Arduino.h>
|
||||
#include "app.h"
|
||||
#include "config.h"
|
||||
#include "types.h"
|
||||
#include "common/macros.h"
|
||||
#include "Addon.h"
|
||||
#include "features.h"
|
||||
|
||||
|
||||
void App::onDidSetupAddons(){
|
||||
|
||||
#ifdef HAS_STATUS
|
||||
status->setStatusAllOn();
|
||||
delay(SECS * 2);
|
||||
status->setStatusAllOff();
|
||||
status->setStatus(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
short App::setFlag(ushort addonId, ushort flag)
|
||||
{
|
||||
Addon *addon = byId(addonId);
|
||||
if (addon)
|
||||
{
|
||||
addon->setFlag(flag);
|
||||
return E_OK;
|
||||
}
|
||||
return ERROR_WARNING;
|
||||
}
|
||||
|
||||
ushort App::numByFlag(ushort flag)
|
||||
{
|
||||
uchar s = addons.size();
|
||||
uchar l = 0;
|
||||
String out = "";
|
||||
for (uchar i = 0; i < s; i++)
|
||||
{
|
||||
Addon *addon = addons[i];
|
||||
if (!!(addon->hasFlag(flag)))
|
||||
{
|
||||
l++;
|
||||
}
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
short App::debug()
|
||||
{
|
||||
#ifndef MEARSURE_PERFORMANCE
|
||||
if (millis() - debugTS > DEBUG_INTERVAL)
|
||||
{
|
||||
uchar s = addons.size();
|
||||
uchar nb = 0;
|
||||
for (uchar i = 0; i < s; i++)
|
||||
{
|
||||
Addon *addon = addons[i];
|
||||
if (addon->hasFlag(DEBUG))
|
||||
{
|
||||
(addon->debug)(&Serial);
|
||||
Serial.println("\n");
|
||||
nb++;
|
||||
}
|
||||
}
|
||||
if (nb)
|
||||
{
|
||||
Serial.println("\n");
|
||||
}
|
||||
debugTS = millis();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
short App::info()
|
||||
{
|
||||
Serial.print("Addon configuration : \n\n");
|
||||
uchar s = addons.size();
|
||||
for (uchar i = 0; i < s; i++)
|
||||
{
|
||||
Addon *addon = addons[i];
|
||||
if (addon->hasFlag(INFO))
|
||||
{
|
||||
addon->info(&Serial);
|
||||
Serial << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Addon *App::byId(short id)
|
||||
{
|
||||
uchar s = addons.size();
|
||||
for (uchar i = 0; i < s; i++)
|
||||
{
|
||||
Addon *addon = addons[i];
|
||||
if (addon->id == id)
|
||||
{
|
||||
return addon;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void App::setup_addons()
|
||||
{
|
||||
#ifdef HAS_STATUS
|
||||
addons.push_back((Addon *)status);
|
||||
#endif
|
||||
addons.push_back((Addon *)cSensor);
|
||||
addons.push_back((Addon *)this);
|
||||
|
||||
uchar s = addons.size();
|
||||
for (uchar i = 0; i < s; i++)
|
||||
{
|
||||
Addon *addon = addons[i];
|
||||
if (addon->hasFlag(SETUP))
|
||||
{
|
||||
addon->setup();
|
||||
}
|
||||
}
|
||||
onDidSetupAddons();
|
||||
}
|
||||
void App::loop_addons()
|
||||
{
|
||||
|
||||
#ifdef MEARSURE_PERFORMANCE
|
||||
millis_t now = millis();
|
||||
#endif
|
||||
|
||||
uchar s = addons.size();
|
||||
for (uchar i = 0; i < s; i++)
|
||||
{
|
||||
Addon *addon = addons[i];
|
||||
if (addon->hasFlag(LOOP))
|
||||
{
|
||||
addon->now = now;
|
||||
addon->loop();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MEARSURE_PERFORMANCE
|
||||
addonLoopTime = millis() - now;
|
||||
if (millis() - printPerfTS > 3000)
|
||||
{
|
||||
printPerfTS = now;
|
||||
Serial << SPACE("Addon loop time") << addonLoopTime << "\n";
|
||||
}
|
||||
#endif
|
||||
debug();
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
#include "app.h"
|
||||
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
#include <PID_v1.h>
|
||||
#include <PID_AutoTune_v0.h>
|
||||
|
||||
byte ATuneModeRemember=2;
|
||||
double input=80, output=50, setpoint=180;
|
||||
double kp=2,ki=0.5,kd=2;
|
||||
|
||||
double kpmodel=1.5, taup=100, theta[50];
|
||||
double outputStart=5;
|
||||
double aTuneStep=50, aTuneNoise=1, aTuneStartValue=100;
|
||||
unsigned int aTuneLookBack=20;
|
||||
|
||||
boolean tuning = false;
|
||||
unsigned long modelTime, serialTime;
|
||||
|
||||
PID myPID(&input, &output, &setpoint,kp,ki,kd, DIRECT);
|
||||
PID_ATune aTune(&input, &output);
|
||||
|
||||
//set to false to connect to the real world
|
||||
boolean useSimulation = true;
|
||||
|
||||
void setup()
|
||||
{
|
||||
if(useSimulation)
|
||||
{
|
||||
for(byte i=0;i<50;i++)
|
||||
{
|
||||
theta[i]=outputStart;
|
||||
}
|
||||
modelTime = 0;
|
||||
}
|
||||
//Setup the pid
|
||||
myPID.SetMode(AUTOMATIC);
|
||||
|
||||
if(tuning)
|
||||
{
|
||||
tuning=false;
|
||||
changeAutoTune();
|
||||
tuning=true;
|
||||
}
|
||||
|
||||
serialTime = 0;
|
||||
Serial.begin(9600);
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
unsigned long now = millis();
|
||||
|
||||
if(!useSimulation)
|
||||
{ //pull the input in from the real world
|
||||
input = analogRead(0);
|
||||
}
|
||||
|
||||
if(tuning)
|
||||
{
|
||||
byte val = (aTune.Runtime());
|
||||
if (val!=0)
|
||||
{
|
||||
tuning = false;
|
||||
}
|
||||
if(!tuning)
|
||||
{ //we're done, set the tuning parameters
|
||||
kp = aTune.GetKp();
|
||||
ki = aTune.GetKi();
|
||||
kd = aTune.GetKd();
|
||||
myPID.SetTunings(kp,ki,kd);
|
||||
AutoTuneHelper(false);
|
||||
}
|
||||
}
|
||||
else myPID.Compute();
|
||||
|
||||
if(useSimulation)
|
||||
{
|
||||
theta[30]=output;
|
||||
if(now>=modelTime)
|
||||
{
|
||||
modelTime +=100;
|
||||
DoModel();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
analogWrite(0,output);
|
||||
}
|
||||
|
||||
//send-receive with processing if it's time
|
||||
if(millis()>serialTime)
|
||||
{
|
||||
SerialReceive();
|
||||
SerialSend();
|
||||
serialTime+=500;
|
||||
}
|
||||
}
|
||||
|
||||
void changeAutoTune()
|
||||
{
|
||||
if(!tuning)
|
||||
{
|
||||
//Set the output to the desired starting frequency.
|
||||
output=aTuneStartValue;
|
||||
aTune.SetNoiseBand(aTuneNoise);
|
||||
aTune.SetOutputStep(aTuneStep);
|
||||
aTune.SetLookbackSec((int)aTuneLookBack);
|
||||
AutoTuneHelper(true);
|
||||
tuning = true;
|
||||
}
|
||||
else
|
||||
{ //cancel autotune
|
||||
aTune.Cancel();
|
||||
tuning = false;
|
||||
AutoTuneHelper(false);
|
||||
}
|
||||
}
|
||||
|
||||
void AutoTuneHelper(boolean start)
|
||||
{
|
||||
if(start)
|
||||
ATuneModeRemember = myPID.GetMode();
|
||||
else
|
||||
myPID.SetMode(ATuneModeRemember);
|
||||
}
|
||||
|
||||
|
||||
void SerialSend()
|
||||
{
|
||||
Serial.print("setpoint: ");Serial.print(setpoint); Serial.print(" ");
|
||||
Serial.print("input: ");Serial.print(input); Serial.print(" ");
|
||||
Serial.print("output: ");Serial.print(output); Serial.print(" ");
|
||||
if(tuning){
|
||||
Serial.println("tuning mode");
|
||||
} else {
|
||||
Serial.print("kp: ");Serial.print(myPID.GetKp());Serial.print(" ");
|
||||
Serial.print("ki: ");Serial.print(myPID.GetKi());Serial.print(" ");
|
||||
Serial.print("kd: ");Serial.print(myPID.GetKd());Serial.println();
|
||||
}
|
||||
}
|
||||
|
||||
void SerialReceive()
|
||||
{
|
||||
if(Serial.available())
|
||||
{
|
||||
char b = Serial.read();
|
||||
Serial.flush();
|
||||
if((b=='1' && !tuning) || (b!='1' && tuning))changeAutoTune();
|
||||
}
|
||||
}
|
||||
|
||||
void DoModel()
|
||||
{
|
||||
//cycle the dead time
|
||||
for(byte i=0;i<49;i++)
|
||||
{
|
||||
theta[i] = theta[i+1];
|
||||
}
|
||||
//compute the input
|
||||
input = (kpmodel / taup) *(theta[0]-outputStart) + input*(1-1/taup) + ((float)random(-10,10))/100;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
#if ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
|
||||
#include <PID_AutoTune_v0.h>
|
||||
|
||||
|
||||
PID_ATune::PID_ATune(double* Input, double* Output)
|
||||
{
|
||||
input = Input;
|
||||
output = Output;
|
||||
controlType =0 ; //default to PI
|
||||
noiseBand = 0.5;
|
||||
running = false;
|
||||
oStep = 30;
|
||||
SetLookbackSec(10);
|
||||
lastTime = millis();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PID_ATune::Cancel()
|
||||
{
|
||||
running = false;
|
||||
}
|
||||
|
||||
int PID_ATune::Runtime()
|
||||
{
|
||||
justevaled=false;
|
||||
if(peakCount>9 && running)
|
||||
{
|
||||
running = false;
|
||||
FinishUp();
|
||||
return 1;
|
||||
}
|
||||
unsigned long now = millis();
|
||||
|
||||
if((now-lastTime)<sampleTime) return false;
|
||||
lastTime = now;
|
||||
double refVal = *input;
|
||||
justevaled=true;
|
||||
if(!running)
|
||||
{ //initialize working variables the first time around
|
||||
peakType = 0;
|
||||
peakCount=0;
|
||||
justchanged=false;
|
||||
absMax=refVal;
|
||||
absMin=refVal;
|
||||
setpoint = refVal;
|
||||
running = true;
|
||||
outputStart = *output;
|
||||
*output = outputStart+oStep;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(refVal>absMax)absMax=refVal;
|
||||
if(refVal<absMin)absMin=refVal;
|
||||
}
|
||||
|
||||
//oscillate the output base on the input's relation to the setpoint
|
||||
|
||||
if(refVal>setpoint+noiseBand) *output = outputStart-oStep;
|
||||
else if (refVal<setpoint-noiseBand) *output = outputStart+oStep;
|
||||
|
||||
|
||||
//bool isMax=true, isMin=true;
|
||||
isMax=true;isMin=true;
|
||||
//id peaks
|
||||
for(int i=nLookBack-1;i>=0;i--)
|
||||
{
|
||||
double val = lastInputs[i];
|
||||
if(isMax) isMax = refVal>val;
|
||||
if(isMin) isMin = refVal<val;
|
||||
lastInputs[i+1] = lastInputs[i];
|
||||
}
|
||||
lastInputs[0] = refVal;
|
||||
if(nLookBack<9)
|
||||
{ //we don't want to trust the maxes or mins until the inputs array has been filled
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(isMax)
|
||||
{
|
||||
if(peakType==0)peakType=1;
|
||||
if(peakType==-1)
|
||||
{
|
||||
peakType = 1;
|
||||
justchanged=true;
|
||||
peak2 = peak1;
|
||||
}
|
||||
peak1 = now;
|
||||
peaks[peakCount] = refVal;
|
||||
|
||||
}
|
||||
else if(isMin)
|
||||
{
|
||||
if(peakType==0)peakType=-1;
|
||||
if(peakType==1)
|
||||
{
|
||||
peakType=-1;
|
||||
peakCount++;
|
||||
justchanged=true;
|
||||
}
|
||||
|
||||
if(peakCount<10)peaks[peakCount] = refVal;
|
||||
}
|
||||
|
||||
if(justchanged && peakCount>2)
|
||||
{ //we've transitioned. check if we can autotune based on the last peaks
|
||||
double avgSeparation = (abs(peaks[peakCount-1]-peaks[peakCount-2])+abs(peaks[peakCount-2]-peaks[peakCount-3]))/2;
|
||||
if( avgSeparation < 0.05*(absMax-absMin))
|
||||
{
|
||||
FinishUp();
|
||||
running = false;
|
||||
return 1;
|
||||
|
||||
}
|
||||
}
|
||||
justchanged=false;
|
||||
return 0;
|
||||
}
|
||||
void PID_ATune::FinishUp()
|
||||
{
|
||||
*output = outputStart;
|
||||
//we can generate tuning parameters!
|
||||
Ku = 4*(2*oStep)/((absMax-absMin)*3.14159);
|
||||
Pu = (double)(peak1-peak2) / 1000;
|
||||
}
|
||||
|
||||
double PID_ATune::GetKp()
|
||||
{
|
||||
return controlType==1 ? 0.6 * Ku : 0.4 * Ku;
|
||||
}
|
||||
|
||||
double PID_ATune::GetKi()
|
||||
{
|
||||
return controlType==1? 1.2*Ku / Pu : 0.48 * Ku / Pu; // Ki = Kc/Ti
|
||||
}
|
||||
|
||||
double PID_ATune::GetKd()
|
||||
{
|
||||
return controlType==1? 0.075 * Ku * Pu : 0; //Kd = Kc * Td
|
||||
}
|
||||
|
||||
void PID_ATune::SetOutputStep(double Step)
|
||||
{
|
||||
oStep = Step;
|
||||
}
|
||||
|
||||
double PID_ATune::GetOutputStep()
|
||||
{
|
||||
return oStep;
|
||||
}
|
||||
|
||||
void PID_ATune::SetControlType(int Type) //0=PI, 1=PID
|
||||
{
|
||||
controlType = Type;
|
||||
}
|
||||
int PID_ATune::GetControlType()
|
||||
{
|
||||
return controlType;
|
||||
}
|
||||
|
||||
void PID_ATune::SetNoiseBand(double Band)
|
||||
{
|
||||
noiseBand = Band;
|
||||
}
|
||||
|
||||
double PID_ATune::GetNoiseBand()
|
||||
{
|
||||
return noiseBand;
|
||||
}
|
||||
|
||||
void PID_ATune::SetLookbackSec(int value)
|
||||
{
|
||||
if (value<1) value = 1;
|
||||
|
||||
if(value<25)
|
||||
{
|
||||
nLookBack = value * 4;
|
||||
sampleTime = 250;
|
||||
}
|
||||
else
|
||||
{
|
||||
nLookBack = 100;
|
||||
sampleTime = value*10;
|
||||
}
|
||||
}
|
||||
|
||||
int PID_ATune::GetLookbackSec()
|
||||
{
|
||||
return nLookBack * sampleTime / 1000;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#ifndef PID_AutoTune_v0
|
||||
#define PID_AutoTune_v0
|
||||
#define LIBRARY_VERSION 0.0.1
|
||||
|
||||
class PID_ATune
|
||||
{
|
||||
|
||||
|
||||
public:
|
||||
//commonly used functions **************************************************************************
|
||||
PID_ATune(double*, double*); // * Constructor. links the Autotune to a given PID
|
||||
int Runtime(); // * Similar to the PID Compue function, returns non 0 when done
|
||||
void Cancel(); // * Stops the AutoTune
|
||||
|
||||
void SetOutputStep(double); // * how far above and below the starting value will the output step?
|
||||
double GetOutputStep(); //
|
||||
|
||||
void SetControlType(int); // * Determies if the tuning parameters returned will be PI (D=0)
|
||||
int GetControlType(); // or PID. (0=PI, 1=PID)
|
||||
|
||||
void SetLookbackSec(int); // * how far back are we looking to identify peaks
|
||||
int GetLookbackSec(); //
|
||||
|
||||
void SetNoiseBand(double); // * the autotune will ignore signal chatter smaller than this value
|
||||
double GetNoiseBand(); // this should be acurately set
|
||||
|
||||
double GetKp(); // * once autotune is complete, these functions contain the
|
||||
double GetKi(); // computed tuning parameters.
|
||||
double GetKd(); //
|
||||
|
||||
private:
|
||||
void FinishUp();
|
||||
bool isMax, isMin;
|
||||
double *input, *output;
|
||||
double setpoint;
|
||||
double noiseBand;
|
||||
int controlType;
|
||||
bool running;
|
||||
unsigned long peak1, peak2, lastTime;
|
||||
int sampleTime;
|
||||
int nLookBack;
|
||||
int peakType;
|
||||
double lastInputs[101];
|
||||
double peaks[10];
|
||||
int peakCount;
|
||||
bool justchanged;
|
||||
bool justevaled;
|
||||
double absMax, absMin;
|
||||
double oStep;
|
||||
double outputStart;
|
||||
double Ku, Pu;
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
#include "bridge.h"
|
||||
#include <Vector.h>
|
||||
#include <Streaming.h>
|
||||
#include "constants.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short key;
|
||||
char *value;
|
||||
} TAddons;
|
||||
|
||||
const TAddons addonsDict[]{};
|
||||
|
||||
static VSL *_instance;
|
||||
class SKeyVal;
|
||||
SKeyVal *clazzMaps[20];
|
||||
Vector<SKeyVal *> clazzes;
|
||||
|
||||
class SKeyValS
|
||||
{
|
||||
public:
|
||||
void *instance;
|
||||
ushort id;
|
||||
SKeyValS() {}
|
||||
SKeyValS(void *_instance, ushort _id) : instance(_instance),
|
||||
id(_id) {}
|
||||
};
|
||||
|
||||
char *getAddonName(short key)
|
||||
{
|
||||
for (uchar i = 0; i < sizeof(addonsDict) / sizeof(TAddons); ++i)
|
||||
{
|
||||
if (addonsDict[i].key == key)
|
||||
{
|
||||
return addonsDict[i].value;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
short getAddonKey(String name)
|
||||
{
|
||||
for (uchar i = 0; i < sizeof(addonsDict) / sizeof(TAddons); ++i)
|
||||
{
|
||||
if (name.equals(String(addonsDict[i].value)))
|
||||
{
|
||||
return addonsDict[i].value;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void VSL::init()
|
||||
{
|
||||
_instance = new VSL();
|
||||
clazzes.setStorage(clazzMaps);
|
||||
}
|
||||
|
||||
VSL *VSL::instance()
|
||||
{
|
||||
if (!_instance)
|
||||
{
|
||||
VSL::init();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
|
||||
SKeyVal *VSL::hasMethod(ushort id, String methodName)
|
||||
{
|
||||
uchar s = clazzes.size();
|
||||
for (uchar i = 0; i < s; i++)
|
||||
{
|
||||
|
||||
SKeyVal *val = clazzes.at(i);
|
||||
if (val->key == id && val->methodName.equals(methodName))
|
||||
{
|
||||
return val;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void VSL::debug()
|
||||
{
|
||||
#ifdef BRIDGE_DEBUG
|
||||
uchar s = clazzes.size();
|
||||
for (uchar i = 0; i < s; i++)
|
||||
{
|
||||
SKeyVal *val = clazzes.at(i);
|
||||
Serial.print(val->className);
|
||||
Serial.print(":");
|
||||
Serial.print(val->methodName);
|
||||
Serial.print("\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SKeyVal *VSL::registerMemberFunction(ushort id, Addon *clazz, char *method, AddonFnPtr ptr, char *ret)
|
||||
{
|
||||
SKeyVal *meth = hasMethod(id, method);
|
||||
if (meth)
|
||||
{
|
||||
#ifdef BRIDGE_DEBUG
|
||||
Serial << "Register class member: "
|
||||
<< SPACE(name << "::" << method)
|
||||
<< "already registered! \n";
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef BRIDGE_DEBUG
|
||||
if (!getAddonKey(name))
|
||||
{
|
||||
Serial.println("invalid addon key");
|
||||
}
|
||||
#endif
|
||||
meth = new SKeyVal(id, clazz, method, ptr);
|
||||
//Serial << "Register member method:"
|
||||
// << SPACE(meth->className << "::" << meth->methodName)
|
||||
// << "\n";
|
||||
clazzes.push_back(meth);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
#ifndef BRDIGE_H
|
||||
#define BRIDGE_H
|
||||
|
||||
#include "Addon.h"
|
||||
#include <WString.h>
|
||||
class App;
|
||||
class SKeyVal;
|
||||
class SKeyValS;
|
||||
|
||||
class SKeyVal
|
||||
{
|
||||
public:
|
||||
short key;
|
||||
void *instance;
|
||||
String methodName;
|
||||
AddonFnPtr mPtr;
|
||||
SKeyVal() {}
|
||||
SKeyVal(ushort _key, void *_instance, String _methodName, AddonFnPtr _mPtr) : key(_key),
|
||||
instance(_instance),
|
||||
methodName(_methodName),
|
||||
mPtr(_mPtr) {}
|
||||
};
|
||||
class VSL
|
||||
{
|
||||
public:
|
||||
SKeyVal *registerMemberFunction(
|
||||
ushort id,
|
||||
Addon *clazz,
|
||||
char *method,
|
||||
AddonFnPtr ptr,
|
||||
char *ret);
|
||||
|
||||
static void init();
|
||||
static VSL *instance();
|
||||
SKeyVal *VSL::hasMethod(ushort id, String method);
|
||||
void debug();
|
||||
};
|
||||
|
||||
#define REGISTER_CLASS_MEMBER_FN(id, inst, methodName, method, ret) \
|
||||
{ \
|
||||
VSL::instance()->registerMemberFunction(id, inst, methodName, method, "2"); \
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace Bridge
|
||||
{
|
||||
|
||||
static const char *START_STR = "<<";
|
||||
static const char *END_STR = ">>";
|
||||
static const char RESPONSE_DEL = ';';
|
||||
static const char *CreateResponse(short id, short error, short ret)
|
||||
{
|
||||
static char response[1024] = {'\0'};
|
||||
snprintf(response, sizeof(response), "%s%d%c%d%c%d%s\r", START_STR, id, RESPONSE_DEL, error, RESPONSE_DEL, ret, END_STR);
|
||||
return response;
|
||||
}
|
||||
static const char *CreateResponse(short id, short error, const char *ret)
|
||||
{
|
||||
static char response[1024] = {'\0'};
|
||||
snprintf(response, sizeof(response), "%s%d%c%d%c%s%s\r", START_STR, id, RESPONSE_DEL, error, RESPONSE_DEL, ret, END_STR);
|
||||
return response;
|
||||
}
|
||||
|
||||
enum ECALLS
|
||||
{
|
||||
EC_COMMAND = 1,
|
||||
EC_METHOD = 2,
|
||||
EC_FUNC = 3,
|
||||
EC_USER = 10
|
||||
};
|
||||
|
||||
enum MessageFlags
|
||||
{
|
||||
NEW = 1,
|
||||
PROCESSING = 2,
|
||||
PROCESSED = 3,
|
||||
DEBUG = 4,
|
||||
RECEIPT = 5,
|
||||
STATE = 6
|
||||
};
|
||||
} // namespace Bridge
|
||||
@@ -0,0 +1,512 @@
|
||||
#ifndef PIN_H
|
||||
#define PIN_H
|
||||
|
||||
// this class doesn't outperform fastgpio but is works with AtmelMega
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#define DDR_HIGH (*_DDR |= _offset) ///< Set the DDR register to HIGH for the pin
|
||||
#define DDR_TOGGLE (*_DDR ^= _offset) ///< Set the DDR register to the inverse for the pin
|
||||
#define DDR_LOW (*_DDR &= _ioffset) ///< Set the DDR register to LOW for the pin
|
||||
|
||||
#define PORT_HIGH (*_PORT |= _offset) ///< Set the PORT register to HIGH for the pin
|
||||
#define PORT_TOGGLE (*_PORT ^= _offset) ///< Set the PORT register to the inverse for the pin
|
||||
#define PORT_LOW (*_PORT &= _ioffset) ///< Set the PORT register to LOW for the pin
|
||||
|
||||
#define DDR_ON (*_DDR & _offset) ///< Get the DDR register for the pin (HIGH, LOW) with other pins forced to 0
|
||||
#define DDR_OFF (*_DDR | _ioffset) ///< Get the DDR register for the pin (HIGH, LOW) with other pins forced to 1
|
||||
|
||||
#define PORT_ON (*_PORT & _offset) ///< Get the PORT register for the pin (HIGH, LOW) with other pins forced to 0
|
||||
#define PORT_OFF (*_PORT | _ioffset) ///< Get the PORT register for the pin (HIGH, LOW) with other pins forced to 1
|
||||
|
||||
#define PIN_ON (*_PIN & _offset) ///< Get the PIN register for the pin (HIGH, LOW) with other pins forced to 0
|
||||
#define PIN_OFF (*_PIN | _ioffset) ///< Get the PIN register for the pin (HIGH, LOW) with other pins forced to 1
|
||||
|
||||
class Pin
|
||||
{
|
||||
public:
|
||||
Pin(uint8_t number)
|
||||
{
|
||||
_number = number;
|
||||
_offset = digitalPinToBitMask(_number);
|
||||
_ioffset = ~_offset;
|
||||
_timer = digitalPinToTimer(_number);
|
||||
_PIN = portInputRegister(digitalPinToPort(_number));
|
||||
_PORT = portOutputRegister(digitalPinToPort(_number));
|
||||
_DDR = portModeRegister(digitalPinToPort(_number));
|
||||
}
|
||||
|
||||
/**
|
||||
Custom board constructor
|
||||
|
||||
getAnalogValue() and setDutyCycle(int value) not supported
|
||||
|
||||
@param number pin number written on board
|
||||
@param offset bit mask used to access pin in registers
|
||||
@param timer timer for pin
|
||||
@param PIN input register for pin
|
||||
@param PORT data register for pin
|
||||
@param DDR data direction register for pin
|
||||
*/
|
||||
Pin(uint8_t number, uint8_t offset, uint8_t timer, volatile uint8_t *PIN, volatile uint8_t *PORT, volatile uint8_t *DDR)
|
||||
{
|
||||
_number = number;
|
||||
_offset = offset;
|
||||
_ioffset = ~_offset;
|
||||
_timer = timer;
|
||||
_PIN = PIN;
|
||||
_PORT = PORT;
|
||||
_DDR = DDR;
|
||||
}
|
||||
|
||||
// ################################# Operators #################################
|
||||
|
||||
/**
|
||||
Get the value of the pin from the PIN register
|
||||
|
||||
@return true if the value of the pin is HIGH, false otherwise
|
||||
*/
|
||||
operator bool() const
|
||||
{
|
||||
return bool(PIN_ON);
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin state
|
||||
|
||||
@param state the state of the pin (HIGH, LOW)
|
||||
*/
|
||||
Pin &operator=(uint8_t state)
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
if (state == LOW)
|
||||
{
|
||||
PORT_LOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
PORT_HIGH;
|
||||
}
|
||||
SREG = oldSREG;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ################################# Getters #################################
|
||||
|
||||
/**
|
||||
Get the pin number
|
||||
|
||||
@return pin number
|
||||
*/
|
||||
uint8_t getNumber()
|
||||
{
|
||||
return _number;
|
||||
}
|
||||
|
||||
/**
|
||||
Get the pin offset
|
||||
|
||||
@return pin offset
|
||||
*/
|
||||
uint8_t getOffset()
|
||||
{
|
||||
return _offset;
|
||||
}
|
||||
|
||||
/**
|
||||
Get the inverse pin offset
|
||||
|
||||
@return inverse pin offset
|
||||
*/
|
||||
uint8_t getInverseOffset()
|
||||
{
|
||||
return _ioffset;
|
||||
}
|
||||
|
||||
/**
|
||||
Get the pin timer
|
||||
|
||||
@return pin timer
|
||||
*/
|
||||
uint8_t getTimer()
|
||||
{
|
||||
return _timer;
|
||||
}
|
||||
|
||||
/**
|
||||
Get a pointer to the PIN register
|
||||
|
||||
@return pointer to the PIN register
|
||||
*/
|
||||
volatile uint8_t *getPIN()
|
||||
{
|
||||
return _PIN;
|
||||
}
|
||||
|
||||
/**
|
||||
Get a pointer to the PORT register
|
||||
|
||||
@return pointer to the PORT register
|
||||
*/
|
||||
volatile uint8_t *getPORT()
|
||||
{
|
||||
return _PORT;
|
||||
}
|
||||
|
||||
/**
|
||||
Get a pointer to the DDR register
|
||||
|
||||
@return pointer to the DDR register
|
||||
*/
|
||||
volatile uint8_t *getDDR()
|
||||
{
|
||||
return _DDR;
|
||||
}
|
||||
|
||||
/**
|
||||
Get the mode of the pin from the DDR register
|
||||
|
||||
@return mode of the pin (OUTPUT, INPUT)
|
||||
*/
|
||||
uint8_t getMode()
|
||||
{
|
||||
if (DDR_ON)
|
||||
{
|
||||
return OUTPUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
return INPUT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Get the state of the pin from the PORT register
|
||||
|
||||
@return state of the pin (HIGH, LOW)
|
||||
*/
|
||||
uint8_t getState()
|
||||
{
|
||||
if (PORT_ON)
|
||||
{
|
||||
return HIGH;
|
||||
}
|
||||
else
|
||||
{
|
||||
return LOW;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Get the value of the pin from the PIN register
|
||||
|
||||
@return value of the pin (HIGH, LOW)
|
||||
*/
|
||||
uint8_t getValue()
|
||||
{
|
||||
if (PIN_ON)
|
||||
{
|
||||
return HIGH;
|
||||
}
|
||||
else
|
||||
{
|
||||
return LOW;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Get the analog value of the pin
|
||||
|
||||
@return analog value of the pin (0-1023)
|
||||
*/
|
||||
uint16_t getAnalogValue()
|
||||
{
|
||||
return analogRead(_number);
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin mode and pin state
|
||||
|
||||
@param mode the mode of the pin (OUTPUT, INPUT)
|
||||
@param state the state of the pin (HIGH, LOW)
|
||||
*/
|
||||
void set(uint8_t mode, uint8_t state)
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
if (mode == INPUT)
|
||||
{
|
||||
DDR_LOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
DDR_HIGH;
|
||||
}
|
||||
if (state == LOW)
|
||||
{
|
||||
PORT_LOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
PORT_HIGH;
|
||||
}
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin mode
|
||||
|
||||
@param mode the mode of the pin (OUTPUT, INPUT)
|
||||
*/
|
||||
void setMode(uint8_t mode)
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
if (mode == INPUT)
|
||||
{
|
||||
DDR_LOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
DDR_HIGH;
|
||||
}
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin state
|
||||
|
||||
@param state the state of the pin (HIGH, LOW)
|
||||
*/
|
||||
void setState(uint8_t state)
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
if (state == LOW)
|
||||
{
|
||||
PORT_LOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
PORT_HIGH;
|
||||
}
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
// #################### Input ####################
|
||||
|
||||
void setInput()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
DDR_LOW;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin pullup resistor to on
|
||||
*/
|
||||
void setPullupOn()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
PORT_HIGH;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin pullup resistor to off
|
||||
*/
|
||||
void setPullupOff()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
PORT_LOW;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin mode to input and the pin pullup resistor to on
|
||||
*/
|
||||
void setInputPullupOn()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
DDR_LOW;
|
||||
PORT_HIGH;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin mode to input and the pin pullup resistor to off
|
||||
*/
|
||||
void setInputPullupOff()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
DDR_LOW;
|
||||
PORT_LOW;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
// #################### Output ####################
|
||||
|
||||
/**
|
||||
Set the pin mode to output
|
||||
*/
|
||||
void setOutput()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
DDR_HIGH;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin output to HIGH
|
||||
*/
|
||||
void setHigh()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
PORT_HIGH;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin output to LOW
|
||||
*/
|
||||
void setLow()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
PORT_LOW;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin mode to output and the pin output to HIGH
|
||||
*/
|
||||
void setOutputHigh()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
DDR_HIGH;
|
||||
PORT_HIGH;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin mode to output and the pin output to LOW
|
||||
*/
|
||||
void setOutputLow()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
DDR_HIGH;
|
||||
PORT_LOW;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the PWM duty cycle
|
||||
|
||||
@param value the duty cycle (0-255)
|
||||
*/
|
||||
void setDutyCycle(int value)
|
||||
{
|
||||
analogWrite(_number, value);
|
||||
}
|
||||
|
||||
// ################################# Utilities #################################
|
||||
|
||||
/**
|
||||
Toggle the pin mode (OUTPUT -> INPUT, INPUT -> OUTPUT)
|
||||
*/
|
||||
void toggleMode()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
DDR_TOGGLE;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Toggle the pin state (HIGH -> LOW, LOW -> HIGH)
|
||||
*/
|
||||
void toggleState()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
PORT_TOGGLE;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
// #################### RC Timer ####################
|
||||
|
||||
/**
|
||||
Set the pin mode to input and decrement a counter until the pin goes HIGH or the counter reaches 0 then set the pin mode to output and return the counter value
|
||||
|
||||
@param count the initial value for the counter to start at (0-65535)
|
||||
|
||||
@return the value remaining on the counter when the pin state went to HIGH or 0 if the counter reached 0
|
||||
*/
|
||||
volatile unsigned int rcTimer(volatile unsigned int count)
|
||||
{
|
||||
uint8_t status;
|
||||
asm volatile(
|
||||
// Save interupt status and disable interupts
|
||||
"in %[status], __SREG__ \n\t" // Store current interupt status in variable 's'
|
||||
"cli \n\t" // Disable interupts
|
||||
|
||||
// Set Pin to input mode to start charging capacitor
|
||||
"ld __tmp_reg__, %a[_DDR] \n\t" // Load the DDR register into r0 (__tmp_reg__)
|
||||
"and __tmp_reg__, %[_ioffset] \n\t" // Apply the bit mask (offset) to r0 (__tmp_reg__)
|
||||
"st %a[_DDR], __tmp_reg__ \n\t" // Store r0 (__tmp_reg__) in the DDR register
|
||||
|
||||
// Count time before Pin becomes high
|
||||
"loop%=: \n\t" // Label for looping
|
||||
//"ld __tmp_reg__,%a[_PIN] \n\t" // Load the PIN register into r0 (__tmp_reg__)
|
||||
"and __tmp_reg__, %[_offset] \n\t" // Apply the bit mask (offset) to r0 (__tmp_reg__)
|
||||
"brne end%= \n\t" // End the loop if r0 (__tmp_reg__) is not equal to zero by branching to label 'end'
|
||||
"dec %[count] \n\t" // Decrement the value of 'count' by one
|
||||
"brne loop%= \n\t" // If the value of 'count' is not equal to zero continue the loop by branching to label 'loop'
|
||||
|
||||
// Done counting
|
||||
"end%=: \n\t" // Label for ending loop
|
||||
// Set Pin to output mode to start discharging capacitor
|
||||
"ld __tmp_reg__, %a[_DDR] \n\t" // Load the DDR register into r0 (__tmp_reg__)
|
||||
"or __tmp_reg__, %[_offset] \n\t" // Apply the bit mask (offset) to r0 (__tmp_reg__)
|
||||
"st %a[_DDR], __tmp_reg__ \n\t" // Store r0 (__tmp_reg__) in the PORT register
|
||||
|
||||
// Restore interupt status
|
||||
"out __SREG__, %[status] \n\t" // Load interupt status from variable 's'
|
||||
|
||||
// Outputs
|
||||
:
|
||||
[ count ] "+r"(count), // The value the counter was at when the pin went high
|
||||
[ status ] "=&r"(status) // The interupt status
|
||||
|
||||
// Inputs
|
||||
:
|
||||
[ _DDR ] "e"(_DDR), // The address of the DDR register for the pin
|
||||
[ _PIN ] "e"(_PIN), // The address of the PIN register for the pin
|
||||
[ _offset ] "r"(_offset), // The bit mask used to access pin in registers
|
||||
[ _ioffset ] "r"(_ioffset) // The inverse bit mask used to access pin in registers
|
||||
);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t _number;
|
||||
uint8_t _offset;
|
||||
uint8_t _ioffset;
|
||||
uint8_t _timer;
|
||||
volatile uint8_t *_PIN;
|
||||
volatile uint8_t *_PORT;
|
||||
volatile uint8_t *_DDR;
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,469 @@
|
||||
#ifndef PIN_GROUP_H
|
||||
#define PIN_GROUP_H
|
||||
|
||||
#include "Pin.h"
|
||||
|
||||
/**
|
||||
Class for simultaneous operations on Arduino I/O pins
|
||||
*/
|
||||
class PinGroup
|
||||
{
|
||||
public:
|
||||
template <size_t N>
|
||||
PinGroup(Pin (&pins)[N])
|
||||
{
|
||||
_offset = pins[0].getOffset();
|
||||
_PIN = pins[0].getPIN();
|
||||
_PORT = pins[0].getPORT();
|
||||
_DDR = pins[0].getDDR();
|
||||
_numbers[0] = pins[0].getNumber();
|
||||
_valid = true;
|
||||
|
||||
for (int i = 1; i < N; i++)
|
||||
{
|
||||
if (_DDR != pins[i].getDDR())
|
||||
{
|
||||
_valid = false;
|
||||
}
|
||||
_offset |= pins[i].getOffset();
|
||||
_numbers[i] = pins[i].getNumber();
|
||||
}
|
||||
_ioffset = ~_offset;
|
||||
}
|
||||
|
||||
// ################################# Operators #################################
|
||||
/**
|
||||
Compare the value of the pin
|
||||
|
||||
@param value the state of the pin (HIGH, LOW)
|
||||
|
||||
@return true if the value of all of the pins are equal to the value passed in, false otherwise
|
||||
*/
|
||||
bool operator==(uint8_t value)
|
||||
{
|
||||
uint8_t status = *_PIN;
|
||||
if ((status & _offset) == _offset)
|
||||
{
|
||||
return (value == HIGH);
|
||||
}
|
||||
else if ((status | _ioffset) == _ioffset)
|
||||
{
|
||||
return (value == LOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Compare the value of the pin
|
||||
|
||||
@param value the state of the pin (HIGH, LOW)
|
||||
|
||||
@return true if the value of all of the pins are not equal to the value passed in, false otherwise
|
||||
*/
|
||||
bool operator!=(uint8_t value)
|
||||
{
|
||||
uint8_t status = *_PIN;
|
||||
if ((status & _offset) == _offset)
|
||||
{
|
||||
return (value == LOW);
|
||||
}
|
||||
else if ((status | _ioffset) == _ioffset)
|
||||
{
|
||||
return (value == HIGH);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin state
|
||||
|
||||
@param state the state of the pin (HIGH, LOW)
|
||||
*/
|
||||
PinGroup &operator=(uint8_t state)
|
||||
{
|
||||
oldSREG = SREG;
|
||||
cli();
|
||||
if (state == LOW)
|
||||
{
|
||||
PORT_LOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
PORT_HIGH;
|
||||
}
|
||||
SREG = oldSREG;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ################################# Getters #################################
|
||||
|
||||
/**
|
||||
Get the pin numbers
|
||||
|
||||
@return array of pin numbers
|
||||
*/
|
||||
uint8_t *getNumbers()
|
||||
{
|
||||
return _numbers;
|
||||
}
|
||||
|
||||
/**
|
||||
Get the pin offset
|
||||
|
||||
@return pin offset
|
||||
*/
|
||||
uint8_t getOffset()
|
||||
{
|
||||
return _offset;
|
||||
}
|
||||
|
||||
/**
|
||||
Get the inverse pin offset
|
||||
|
||||
@return inverse pin offset
|
||||
*/
|
||||
uint8_t getInverseOffset()
|
||||
{
|
||||
return _ioffset;
|
||||
}
|
||||
|
||||
/**
|
||||
Get a pointer to the PIN register
|
||||
|
||||
@return pointer to the PIN register
|
||||
*/
|
||||
volatile uint8_t *getPIN()
|
||||
{
|
||||
return _PIN;
|
||||
}
|
||||
|
||||
/**
|
||||
Get a pointer to the PORT register
|
||||
|
||||
@return pointer to the PORT register
|
||||
*/
|
||||
volatile uint8_t *getPORT()
|
||||
{
|
||||
return _PORT;
|
||||
}
|
||||
|
||||
/**
|
||||
Get a pointer to the DDR register
|
||||
|
||||
@return pointer to the DDR register
|
||||
*/
|
||||
volatile uint8_t *getDDR()
|
||||
{
|
||||
return _DDR;
|
||||
}
|
||||
|
||||
/**
|
||||
Get the mode of the pin from the DDR register
|
||||
|
||||
@return mode of the pin (OUTPUT, INPUT, -1)
|
||||
*/
|
||||
uint8_t getMode()
|
||||
{
|
||||
uint8_t status = *_DDR;
|
||||
if ((status & _offset) == _offset)
|
||||
{
|
||||
return OUTPUT;
|
||||
}
|
||||
else if ((status | _ioffset) == _ioffset)
|
||||
{
|
||||
return INPUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Get the state of the pin from the PORT register
|
||||
|
||||
@return state of the pin (HIGH, LOW, -1)
|
||||
*/
|
||||
uint8_t getState()
|
||||
{
|
||||
uint8_t status = *_PORT;
|
||||
if ((status & _offset) == _offset)
|
||||
{
|
||||
return HIGH;
|
||||
}
|
||||
else if ((status | _ioffset) == _ioffset)
|
||||
{
|
||||
return LOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Get the value of the pin from the PIN register
|
||||
|
||||
@return value of the pin (HIGH, LOW, -1)
|
||||
*/
|
||||
uint8_t getValue()
|
||||
{
|
||||
uint8_t status = *_PIN;
|
||||
if ((status & _offset) == _offset)
|
||||
{
|
||||
return HIGH;
|
||||
}
|
||||
else if ((status | _ioffset) == _ioffset)
|
||||
{
|
||||
return LOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Check the group to ensure all pins use the same registers
|
||||
|
||||
@return true if the pins in the group all use the same registers, false otherwise
|
||||
*/
|
||||
bool isValid()
|
||||
{
|
||||
return _valid;
|
||||
}
|
||||
|
||||
// ################################# Setters #################################
|
||||
|
||||
// #################### Generic ####################
|
||||
|
||||
/**
|
||||
Set the pin mode and pin state
|
||||
|
||||
@param mode the mode of the pin (OUTPUT, INPUT)
|
||||
@param state the state of the pin (HIGH, LOW)
|
||||
*/
|
||||
void set(uint8_t mode, uint8_t state)
|
||||
{
|
||||
oldSREG = SREG;
|
||||
cli();
|
||||
if (mode == INPUT)
|
||||
{
|
||||
DDR_LOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
DDR_HIGH;
|
||||
}
|
||||
if (state == LOW)
|
||||
{
|
||||
PORT_LOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
PORT_HIGH;
|
||||
}
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin mode
|
||||
|
||||
@param mode the mode of the pin (OUTPUT, INPUT)
|
||||
*/
|
||||
void setMode(uint8_t mode)
|
||||
{
|
||||
oldSREG = SREG;
|
||||
cli();
|
||||
if (mode == INPUT)
|
||||
{
|
||||
DDR_LOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
DDR_HIGH;
|
||||
}
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin state
|
||||
|
||||
@param state the state of the pin (HIGH, LOW)
|
||||
*/
|
||||
void setState(uint8_t state)
|
||||
{
|
||||
oldSREG = SREG;
|
||||
cli();
|
||||
if (state == LOW)
|
||||
{
|
||||
PORT_LOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
PORT_HIGH;
|
||||
}
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
// #################### Input ####################
|
||||
|
||||
/**
|
||||
Set the pin mode to input
|
||||
*/
|
||||
void setInput()
|
||||
{
|
||||
oldSREG = SREG;
|
||||
cli();
|
||||
DDR_LOW;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin pullup resistor to on
|
||||
*/
|
||||
void setPullupOn()
|
||||
{
|
||||
oldSREG = SREG;
|
||||
cli();
|
||||
PORT_HIGH;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin pullup resistor to off
|
||||
*/
|
||||
void setPullupOff()
|
||||
{
|
||||
oldSREG = SREG;
|
||||
cli();
|
||||
PORT_LOW;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin mode to input and the pin pullup resistor to on
|
||||
*/
|
||||
void setInputPullupOn()
|
||||
{
|
||||
oldSREG = SREG;
|
||||
cli();
|
||||
DDR_LOW;
|
||||
PORT_HIGH;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin mode to input and the pin pullup resistor to off
|
||||
*/
|
||||
void setInputPullupOff()
|
||||
{
|
||||
oldSREG = SREG;
|
||||
cli();
|
||||
DDR_LOW;
|
||||
PORT_LOW;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
// #################### Output ####################
|
||||
|
||||
/**
|
||||
Set the pin mode to output
|
||||
*/
|
||||
void setOutput()
|
||||
{
|
||||
oldSREG = SREG;
|
||||
cli();
|
||||
DDR_HIGH;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin output to HIGH
|
||||
*/
|
||||
void setHigh()
|
||||
{
|
||||
oldSREG = SREG;
|
||||
cli();
|
||||
PORT_HIGH;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin output to LOW
|
||||
*/
|
||||
void setLow()
|
||||
{
|
||||
oldSREG = SREG;
|
||||
cli();
|
||||
PORT_LOW;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin mode to output and the pin output to HIGH
|
||||
*/
|
||||
void setOutputHigh()
|
||||
{
|
||||
oldSREG = SREG;
|
||||
cli();
|
||||
DDR_HIGH;
|
||||
PORT_HIGH;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the pin mode to output and the pin output to LOW
|
||||
*/
|
||||
void setOutputLow()
|
||||
{
|
||||
oldSREG = SREG;
|
||||
cli();
|
||||
DDR_HIGH;
|
||||
PORT_LOW;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
// ################################# Utilities #################################
|
||||
|
||||
// #################### Toggle ####################
|
||||
|
||||
/**
|
||||
Toggle the pin mode (OUTPUT -> INPUT, INPUT -> OUTPUT)
|
||||
*/
|
||||
void toggleMode()
|
||||
{
|
||||
oldSREG = SREG;
|
||||
cli();
|
||||
DDR_TOGGLE;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
/**
|
||||
Toggle the pin state (HIGH -> LOW, LOW -> HIGH)
|
||||
*/
|
||||
void toggleState()
|
||||
{
|
||||
oldSREG = SREG;
|
||||
cli();
|
||||
PORT_TOGGLE;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t _numbers[8];
|
||||
uint8_t _offset;
|
||||
uint8_t _ioffset;
|
||||
bool _valid;
|
||||
uint8_t oldSREG;
|
||||
volatile uint8_t *_PIN;
|
||||
volatile uint8_t *_PORT;
|
||||
volatile uint8_t *_DDR;
|
||||
};
|
||||
@@ -0,0 +1,98 @@
|
||||
#ifndef MACROS_H
|
||||
#define MACROS_H
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
// Macros for adding
|
||||
#define INC_0 1
|
||||
#define INC_1 2
|
||||
#define INC_2 3
|
||||
#define INC_3 4
|
||||
#define INC_4 5
|
||||
#define INC_5 6
|
||||
#define INC_6 7
|
||||
#define INC_7 8
|
||||
#define INC_8 9
|
||||
#define INCREMENT_(n) INC_ ##n
|
||||
#define INCREMENT(n) INCREMENT_(n)
|
||||
|
||||
// Macros for subtracting
|
||||
#define DEC_1 0
|
||||
#define DEC_2 1
|
||||
#define DEC_3 2
|
||||
#define DEC_4 3
|
||||
#define DEC_5 4
|
||||
#define DEC_6 5
|
||||
#define DEC_7 6
|
||||
#define DEC_8 7
|
||||
#define DEC_9 8
|
||||
#define DECREMENT_(n) DEC_ ##n
|
||||
#define DECREMENT(n) DECREMENT_(n)
|
||||
|
||||
// compiler - & C quirks
|
||||
#define FORCE_INLINE __attribute__((always_inline)) inline
|
||||
#define _UNUSED __attribute__((unused))
|
||||
|
||||
// fallback noop
|
||||
#define NOOP do{} while(0)
|
||||
|
||||
//Option testing
|
||||
#define _CAT(a, ...) a ## __VA_ARGS__
|
||||
#define SWITCH_ENABLED_ 1
|
||||
#define ENABLED(b) _CAT(SWITCH_ENABLED_, b)
|
||||
|
||||
// time
|
||||
#define PENDING(NOW,SOON) ((long)(NOW-(SOON))<0)
|
||||
#define ELAPSED(NOW,SOON) (!PENDING(NOW,SOON))
|
||||
|
||||
#define MMM_TO_MMS(MM_M) ((MM_M)/60.0f)
|
||||
#define MMS_TO_MMM(MM_S) ((MM_S)*60.0f)
|
||||
#define HOUR_MS ((millis_t)1000 * (millis_t)(60 * 60))
|
||||
#define MIN_MS ((millis_t)1000 * (millis_t)(60))
|
||||
#define SECS ((millis_t)1000)
|
||||
|
||||
// bit masks
|
||||
#undef _BV
|
||||
#define _BV(b) (1 << (b))
|
||||
#define TEST(n,b) !!((n)&_BV(b))
|
||||
#define SBI(n,b) (n |= _BV(b))
|
||||
#define CBI(n,b) (n &= ~_BV(b))
|
||||
#define SET_BIT_TO(N,B,TF) do{ if (TF) SBI(N,B); else CBI(N,B); }while(0)
|
||||
|
||||
#define _BV32(b) (1UL << (b))
|
||||
#define TEST32(n,b) !!((n)&_BV32(b))
|
||||
#define SBI32(n,b) (n |= _BV32(b))
|
||||
#define CBI32(n,b) (n &= ~_BV32(b))
|
||||
#define SIGN(a) ((a>0)-(a<0))
|
||||
|
||||
// math basics
|
||||
|
||||
#define WITHIN(V,L,H) ((V) >= (L) && (V) <= (H))
|
||||
#define NUMERIC(a) WITHIN(a, '0', '9')
|
||||
#define DECIMAL(a) (NUMERIC(a) || a == '.')
|
||||
#define NUMERIC_SIGNED(a) (NUMERIC(a) || (a) == '-' || (a) == '+')
|
||||
#define DECIMAL_SIGNED(a) (DECIMAL(a) || (a) == '-' || (a) == '+')
|
||||
#define COUNT(a) (sizeof(a)/sizeof(*a))
|
||||
#define ZERO(a) memset(a,0,sizeof(a))
|
||||
#define COPY(a,b) memcpy(a,b,MIN(sizeof(a),sizeof(b)))
|
||||
|
||||
|
||||
// #define M_PI 3.14159265358979323846f
|
||||
#define RADIANS(d) ((d)*M_PI/180.0f)
|
||||
#define DEGREES(r) ((r)*180.0f/M_PI)
|
||||
#define CEILING(x,y) (((x) + (y) - 1) / (y))
|
||||
|
||||
// Macros for initializing arrays
|
||||
#define ARRAY_6(v1, v2, v3, v4, v5, v6, ...) { v1, v2, v3, v4, v5, v6 }
|
||||
#define ARRAY_5(v1, v2, v3, v4, v5, ...) { v1, v2, v3, v4, v5 }
|
||||
#define ARRAY_4(v1, v2, v3, v4, ...) { v1, v2, v3, v4 }
|
||||
#define ARRAY_3(v1, v2, v3, ...) { v1, v2, v3 }
|
||||
#define ARRAY_2(v1, v2, ...) { v1, v2 }
|
||||
#define ARRAY_1(v1, ...) { v1 }
|
||||
|
||||
#define _ARRAY_N(N, ...) ARRAY_ ##N(__VA_ARGS__)
|
||||
#define ARRAY_N(N, ...) _ARRAY_N(N, __VA_ARGS__)
|
||||
|
||||
#define SPACE(A) " " << A << " "
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef PPMATH_H
|
||||
#define PPMATH_H
|
||||
|
||||
template <typename T>
|
||||
T clamp(const T &value, const T &low, const T &high)
|
||||
{
|
||||
return value < low ? low : (value > high ? high : value);
|
||||
}
|
||||
|
||||
#define RANGE(i, min, max) ((i > min) && (i < max)) ? true : false
|
||||
|
||||
#define NCLAMP(x, min, max) (x - min) / (max - min)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,136 @@
|
||||
#ifndef TIMER_H
|
||||
#define TIMER_H
|
||||
|
||||
#if defined(ARDUINO) && ARDUINO >= 100
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include <WProgram.h>
|
||||
#endif
|
||||
|
||||
#include "macros.h"
|
||||
|
||||
#ifndef TIMER_MAX_TASKS
|
||||
#define TIMER_MAX_TASKS 0x10
|
||||
#endif
|
||||
|
||||
template <
|
||||
size_t max_tasks = TIMER_MAX_TASKS, /* max allocated tasks */
|
||||
unsigned long (*time_func)() = millis /* time function for timer */
|
||||
>
|
||||
class Timer
|
||||
{
|
||||
public:
|
||||
typedef bool (*handler_t)(void *opaque); /* task handler func signature */
|
||||
/* Calls handler with opaque as argument in delay units of time */
|
||||
bool
|
||||
in(unsigned long delay, handler_t h, void *opaque = NULL)
|
||||
{
|
||||
return add_task(time_func(), delay, h, opaque);
|
||||
}
|
||||
|
||||
/* Calls handler with opaque as argument at time */
|
||||
bool
|
||||
at(unsigned long time, handler_t h, void *opaque = NULL)
|
||||
{
|
||||
const unsigned long now = time_func();
|
||||
return add_task(now, time - now, h, opaque);
|
||||
}
|
||||
|
||||
/* Calls handler with opaque as argument every interval units of time */
|
||||
bool
|
||||
every(unsigned long interval, handler_t h, void *opaque = NULL)
|
||||
{
|
||||
return add_task(time_func(), interval, h, opaque, interval);
|
||||
}
|
||||
|
||||
|
||||
/* Ticks the timer forward - call this function in loop() */
|
||||
void
|
||||
tick()
|
||||
{
|
||||
tick(time_func());
|
||||
}
|
||||
|
||||
/* Ticks the timer forward - call this function in loop() */
|
||||
inline void
|
||||
tick(unsigned long t)
|
||||
{
|
||||
for (size_t i = 0; i < max_tasks; ++i)
|
||||
{
|
||||
struct task *const task = &tasks[i];
|
||||
const unsigned long duration = t - task->start;
|
||||
|
||||
if (task->handler && duration >= task->expires)
|
||||
{
|
||||
task->repeat = task->handler(task->opaque) && task->repeat;
|
||||
|
||||
if (task->repeat)
|
||||
task->start = t;
|
||||
else
|
||||
remove(task);
|
||||
}else{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct task
|
||||
{
|
||||
handler_t handler; /* task handler callback func */
|
||||
void *opaque; /* argument given to the callback handler */
|
||||
unsigned long start,
|
||||
expires, /* when the task expires */
|
||||
repeat; /* repeat task */
|
||||
} tasks[max_tasks];
|
||||
|
||||
inline void
|
||||
remove(struct task *task)
|
||||
{
|
||||
task->handler = NULL;
|
||||
task->opaque = NULL;
|
||||
task->start = 0;
|
||||
task->expires = 0;
|
||||
task->repeat = 0;
|
||||
}
|
||||
|
||||
inline struct task *
|
||||
next_task_slot()
|
||||
{
|
||||
for (size_t i = 0; i < max_tasks; ++i)
|
||||
{
|
||||
struct task *const slot = &tasks[i];
|
||||
if (slot->handler == NULL)
|
||||
return slot;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline struct task *
|
||||
add_task(unsigned long start, unsigned long expires,
|
||||
handler_t h, void *opaque, bool repeat = 0)
|
||||
{
|
||||
struct task *const slot = next_task_slot();
|
||||
|
||||
if (!slot){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
slot->handler = h;
|
||||
slot->opaque = opaque;
|
||||
slot->start = start;
|
||||
slot->expires = expires;
|
||||
slot->repeat = repeat;
|
||||
|
||||
return slot;
|
||||
}
|
||||
};
|
||||
|
||||
/* create a timer with the default settings */
|
||||
inline Timer<>
|
||||
timer_create_default()
|
||||
{
|
||||
return Timer<>();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,80 @@
|
||||
#ifndef POS3_ANALOG_H
|
||||
#define POS3_ANALOG_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "../enums.h"
|
||||
#include "../common/ppmath.h"
|
||||
|
||||
class Pos3Analog
|
||||
{
|
||||
public:
|
||||
Pos3Analog(short _upPin, short _downPin) : upPin(_upPin), downPin(_downPin)
|
||||
{
|
||||
}
|
||||
|
||||
short setup()
|
||||
{
|
||||
pinMode(upPin, INPUT_PULLUP);
|
||||
pinMode(downPin, INPUT_PULLUP);
|
||||
last_switch = loop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
short loop()
|
||||
{
|
||||
uchar newDirection = this->read();
|
||||
|
||||
if (newDirection != this->switch_pos)
|
||||
{
|
||||
this->last_switch = this->switch_pos;
|
||||
}
|
||||
this->switch_pos = newDirection;
|
||||
return this->switch_pos;
|
||||
}
|
||||
|
||||
short last_switch = -1; // Track last switch position
|
||||
short switch_pos = -1; // Current switch position
|
||||
short upPin;
|
||||
short downPin;
|
||||
|
||||
|
||||
private:
|
||||
uchar read()
|
||||
{
|
||||
|
||||
bool up = RANGE(analogRead(upPin), 240, 260);
|
||||
bool down = RANGE(analogRead(downPin), 240, 260);
|
||||
|
||||
uchar newDirection = 0;
|
||||
|
||||
if (up)
|
||||
{
|
||||
newDirection = POS3_DIRECTION::UP;
|
||||
}
|
||||
if (down)
|
||||
{
|
||||
newDirection = POS3_DIRECTION::DOWN;
|
||||
}
|
||||
if (!up && !down)
|
||||
{
|
||||
newDirection = POS3_DIRECTION::MIDDLE;
|
||||
}
|
||||
if (up && down)
|
||||
{
|
||||
newDirection = POS3_DIRECTION::INVALID;
|
||||
}
|
||||
return newDirection;
|
||||
}
|
||||
|
||||
bool changed()
|
||||
{
|
||||
return last_switch != switch_pos;
|
||||
}
|
||||
|
||||
bool clear()
|
||||
{
|
||||
return last_switch = switch_pos;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,81 @@
|
||||
#ifndef POS3_H
|
||||
#define POS3_H
|
||||
|
||||
#include <Bounce2.h>
|
||||
#include "../enums.h"
|
||||
|
||||
class Pos3
|
||||
{
|
||||
public:
|
||||
Pos3(int _upPin, int _downPin) : upPin(_upPin), downPin(_downPin)
|
||||
{
|
||||
}
|
||||
|
||||
int setup()
|
||||
{
|
||||
|
||||
this->debouncerUp = Bounce();
|
||||
this->debouncerUp.attach(this->upPin, INPUT_PULLUP);
|
||||
this->debouncerUp.interval(25);
|
||||
|
||||
this->debouncerDown = Bounce();
|
||||
this->debouncerDown.attach(this->downPin, INPUT_PULLUP);
|
||||
this->debouncerDown.interval(25);
|
||||
return 0;
|
||||
}
|
||||
int loop()
|
||||
{
|
||||
int newDirection = this->read();
|
||||
|
||||
if (newDirection != this->switch_pos)
|
||||
{
|
||||
this->last_switch = this->switch_pos;
|
||||
}
|
||||
this->switch_pos = newDirection;
|
||||
|
||||
return this->switch_pos;
|
||||
}
|
||||
|
||||
int last_switch = -1; // Track last switch position
|
||||
int switch_pos = -1; // Current switch position
|
||||
|
||||
protected:
|
||||
int upPin;
|
||||
int downPin;
|
||||
|
||||
Bounce debouncerUp;
|
||||
Bounce debouncerDown;
|
||||
|
||||
private:
|
||||
int read()
|
||||
{
|
||||
|
||||
this->debouncerUp.update();
|
||||
this->debouncerDown.update();
|
||||
|
||||
bool up = this->debouncerUp.read() == 0 ? true : false;
|
||||
bool down = this->debouncerDown.read() == 0 ? true : false;
|
||||
|
||||
int newDirection = 0;
|
||||
|
||||
if (up)
|
||||
{
|
||||
newDirection = POS3_DIRECTION::UP;
|
||||
}
|
||||
if (down)
|
||||
{
|
||||
newDirection = POS3_DIRECTION::DOWN;
|
||||
}
|
||||
if (!up && !down)
|
||||
{
|
||||
newDirection = POS3_DIRECTION::MIDDLE;
|
||||
}
|
||||
if (up && down)
|
||||
{
|
||||
newDirection = POS3_DIRECTION::INVALID;
|
||||
}
|
||||
return newDirection;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
#ifndef TEMPERATURE_SENSOR_H
|
||||
#define TEMPERATURE_SENSOR_H
|
||||
|
||||
#include <max6675.h>
|
||||
#include "../config.h"
|
||||
#include "../macros.h"
|
||||
#include "../time.h"
|
||||
|
||||
class TemperatureSensor
|
||||
{
|
||||
|
||||
public:
|
||||
TemperatureSensor(short sck, short cs, short so, short _max, short _interval) : ktc(MAX6675(sck, cs, so)),
|
||||
temperature(),
|
||||
temperature_TS(millis()),
|
||||
maxTemp(_max),
|
||||
interval(_interval) {}
|
||||
|
||||
bool ok()
|
||||
{
|
||||
return temperature < maxTemp;
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
if (millis() - temperature_TS > interval)
|
||||
{
|
||||
temperature_TS = millis();
|
||||
temperature = ktc.readCelsius();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
MAX6675 ktc;
|
||||
short temperature;
|
||||
short maxTemp;
|
||||
short interval;
|
||||
millis_t temperature_TS;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,91 @@
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#include "enums.h"
|
||||
#include "common/macros.h"
|
||||
#include <Controllino.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Core settings
|
||||
//
|
||||
|
||||
#define LOOP_DELAY 500 // Our frame time, exluding delays in some places
|
||||
#define BOOT_DELAY 1000 // Wait at least this amount in ms after boot before doing anything
|
||||
|
||||
// Please consider to set this to false for production - especially with the full feature set since this is requiring extra
|
||||
// time for the serial communication and will affect the overall framerate/performance
|
||||
// #define DEBUG true
|
||||
|
||||
#define DEBUG_INTERVAL 1000
|
||||
#define DEBUG_BAUD_RATE 19200 // Serial port speed
|
||||
|
||||
#define RELAY_ON 0 // The relay bank's on value (eg: normally closed)
|
||||
#define RELAY_OFF 255 // The relay bank's off value (eg: normally closed)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Machine settings
|
||||
//
|
||||
|
||||
// #define USE_MEGA // On Arduino Uno we have only limited ports which are not enough to enable all features.
|
||||
#define USE_CONTROLLINO
|
||||
// #define HAS_AUTOREVERSE
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// General switches
|
||||
|
||||
// Reset button - uncomment to activate. This will unlock the fatal state in case of jamming or other problems.
|
||||
//#define HAS_RESET
|
||||
#define RESET_PIN 3
|
||||
#define RESET_DELAY 1000 // Time to wait when reset has been hit or hold. This is good to give the system some time
|
||||
#define RESET_FATAL true // Makes the reset button act as emergency button. User has to go into stop positon first to unlock it again otherwise it keeps spinning after the RESET_DELAY
|
||||
#define RESET_INTERVAL 300 // Interval to read the NC reset button
|
||||
#define RESET_NC true // Toggles the reset button type between NC and NO
|
||||
|
||||
// Operation Mode Switch
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Heating Cell/Partition
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Feedback
|
||||
|
||||
// Status LEDS (ok, error) - uncomment to activate
|
||||
#define HAS_STATUS
|
||||
#define STATUS_OK_PIN CONTROLLINO_D2
|
||||
#define STATUS_ERROR_PIN CONTROLLINO_D3
|
||||
|
||||
|
||||
#define FIRMWARE_VERSION 0.7
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// HMI Bridge
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// externals
|
||||
//
|
||||
|
||||
// pull in internal constants
|
||||
#include "constants.h"
|
||||
|
||||
// pull in internal configs
|
||||
#include "config_adv.h"
|
||||
|
||||
// The user_config.h is initially added to the github repository but changes will be ignored via .gitignore. Please keep this file safe and possibly
|
||||
// on a per tenant base stored. You can override parameters in this file by using #undef SOME_PARAMETER and then re-define again if needed, otherwise disable
|
||||
// default features by using #undef FEATURE_OR_PARAMETER.
|
||||
// This presents the possibilty to play with the code whilst staying in the loop with latest updates.
|
||||
#include "user_config.h"
|
||||
|
||||
// At last we check all configs and spit compiler errors
|
||||
#include "config_validator.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,153 @@
|
||||
#ifndef known_16bit_timers_header_
|
||||
#define known_16bit_timers_header_
|
||||
|
||||
// Wiring-S
|
||||
//
|
||||
#if defined(__AVR_ATmega644P__) && defined(WIRING)
|
||||
#define TIMER1_A_PIN 5
|
||||
#define TIMER1_B_PIN 4
|
||||
#define TIMER1_ICP_PIN 6
|
||||
|
||||
// Teensy 2.0
|
||||
//
|
||||
#elif defined(__AVR_ATmega32U4__) && defined(CORE_TEENSY)
|
||||
#define TIMER1_A_PIN 14
|
||||
#define TIMER1_B_PIN 15
|
||||
#define TIMER1_C_PIN 4
|
||||
#define TIMER1_ICP_PIN 22
|
||||
#define TIMER1_CLK_PIN 11
|
||||
#define TIMER3_A_PIN 9
|
||||
#define TIMER3_ICP_PIN 10
|
||||
|
||||
// Teensy++ 2.0
|
||||
#elif defined(__AVR_AT90USB1286__) && defined(CORE_TEENSY)
|
||||
#define TIMER1_A_PIN 25
|
||||
#define TIMER1_B_PIN 26
|
||||
#define TIMER1_C_PIN 27
|
||||
#define TIMER1_ICP_PIN 4
|
||||
#define TIMER1_CLK_PIN 6
|
||||
#define TIMER3_A_PIN 16
|
||||
#define TIMER3_B_PIN 15
|
||||
#define TIMER3_C_PIN 14
|
||||
#define TIMER3_ICP_PIN 17
|
||||
#define TIMER3_CLK_PIN 13
|
||||
|
||||
// Teensy 3.0
|
||||
//
|
||||
#elif defined(__MK20DX128__)
|
||||
#define TIMER1_A_PIN 3
|
||||
#define TIMER1_B_PIN 4
|
||||
#define TIMER1_ICP_PIN 4
|
||||
|
||||
// Teensy 3.1 / Teensy 3.2
|
||||
//
|
||||
#elif defined(__MK20DX256__)
|
||||
#define TIMER1_A_PIN 3
|
||||
#define TIMER1_B_PIN 4
|
||||
#define TIMER1_ICP_PIN 4
|
||||
#define TIMER3_A_PIN 32
|
||||
#define TIMER3_B_PIN 25
|
||||
#define TIMER3_ICP_PIN 32
|
||||
|
||||
// Teensy 3.5 / Teensy 3.6
|
||||
//
|
||||
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||
#define TIMER1_A_PIN 3
|
||||
#define TIMER1_B_PIN 4
|
||||
#define TIMER1_ICP_PIN 4
|
||||
#define TIMER3_A_PIN 29
|
||||
#define TIMER3_B_PIN 30
|
||||
#define TIMER3_ICP_PIN 29
|
||||
|
||||
// Teensy-LC
|
||||
//
|
||||
#elif defined(__MKL26Z64__)
|
||||
#define TIMER1_A_PIN 16
|
||||
#define TIMER1_B_PIN 17
|
||||
#define TIMER1_ICP_PIN 17
|
||||
#define TIMER3_A_PIN 3
|
||||
#define TIMER3_B_PIN 4
|
||||
#define TIMER3_ICP_PIN 4
|
||||
|
||||
// Arduino Mega
|
||||
//
|
||||
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||
#define TIMER1_A_PIN 11
|
||||
#define TIMER1_B_PIN 12
|
||||
#define TIMER1_C_PIN 13
|
||||
#define TIMER3_A_PIN 5
|
||||
#define TIMER3_B_PIN 2
|
||||
#define TIMER3_C_PIN 3
|
||||
#define TIMER4_A_PIN 6
|
||||
#define TIMER4_B_PIN 7
|
||||
#define TIMER4_C_PIN 8
|
||||
#define TIMER4_ICP_PIN 49
|
||||
#define TIMER5_A_PIN 46
|
||||
#define TIMER5_B_PIN 45
|
||||
#define TIMER5_C_PIN 44
|
||||
#define TIMER3_ICP_PIN 48
|
||||
#define TIMER3_CLK_PIN 47
|
||||
|
||||
// Arduino Leonardo, Yun, etc
|
||||
//
|
||||
#elif defined(__AVR_ATmega32U4__)
|
||||
#define TIMER1_A_PIN 9
|
||||
#define TIMER1_B_PIN 10
|
||||
#define TIMER1_C_PIN 11
|
||||
#define TIMER1_ICP_PIN 4
|
||||
#define TIMER1_CLK_PIN 12
|
||||
#define TIMER3_A_PIN 5
|
||||
#define TIMER3_ICP_PIN 13
|
||||
|
||||
// Uno, Duemilanove, LilyPad, etc
|
||||
//
|
||||
#elif defined (__AVR_ATmega168__) || defined (__AVR_ATmega328P__)
|
||||
#define TIMER1_A_PIN 9
|
||||
#define TIMER1_B_PIN 10
|
||||
#define TIMER1_ICP_PIN 8
|
||||
#define TIMER1_CLK_PIN 5
|
||||
|
||||
// Sanguino
|
||||
//
|
||||
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
|
||||
#define TIMER1_A_PIN 13
|
||||
#define TIMER1_B_PIN 12
|
||||
#define TIMER1_ICP_PIN 14
|
||||
#define TIMER1_CLK_PIN 1
|
||||
|
||||
// Wildfire - Wicked Devices
|
||||
//
|
||||
#elif defined(__AVR_ATmega1284P__) && defined(WILDFIRE_VERSION) && WILDFIRE_VERSION >= 3
|
||||
#define TIMER1_A_PIN 5 // PD5
|
||||
#define TIMER1_B_PIN 8 // PD4
|
||||
#define TIMER1_ICP_PIN 6 // PD6
|
||||
#define TIMER1_CLK_PIN 23 // PB1
|
||||
#define TIMER3_A_PIN 12 // PB6
|
||||
#define TIMER3_B_PIN 13 // PB7
|
||||
#define TIMER3_ICP_PIN 9 // PB5
|
||||
#define TIMER3_CLK_PIN 0 // PD0
|
||||
#elif defined(__AVR_ATmega1284P__) && defined(WILDFIRE_VERSION) && WILDFIRE_VERSION < 3
|
||||
#define TIMER1_A_PIN 5 // PD5
|
||||
#define TIMER1_B_PIN 4 // PD4
|
||||
#define TIMER1_ICP_PIN 6 // PD6
|
||||
#define TIMER1_CLK_PIN 15 // PB1
|
||||
#define TIMER3_A_PIN 12 // PB6
|
||||
#define TIMER3_B_PIN 13 // PB7
|
||||
#define TIMER3_ICP_PIN 11 // PB5
|
||||
#define TIMER3_CLK_PIN 0 // PD0
|
||||
|
||||
// Mighty-1284 - Maniacbug
|
||||
//
|
||||
#elif defined(__AVR_ATmega1284P__)
|
||||
#define TIMER1_A_PIN 12 // PD5
|
||||
#define TIMER1_B_PIN 13 // PD4
|
||||
#define TIMER1_ICP_PIN 14 // PD6
|
||||
#define TIMER1_CLK_PIN 1 // PB1
|
||||
#define TIMER3_A_PIN 6 // PB6
|
||||
#define TIMER3_B_PIN 7 // PB7
|
||||
#define TIMER3_ICP_PIN 5 // PB5
|
||||
#define TIMER3_CLK_PIN 8 // PD0
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef CONFIG_ADV_H
|
||||
#define CONFIG_ADV_H
|
||||
|
||||
|
||||
// Error codes
|
||||
//
|
||||
#define E_MSG_OK "Ok"
|
||||
|
||||
// common operating failures
|
||||
#define E_OK 0 //all good
|
||||
#define E_STUCK 100 //Shredder stuck
|
||||
|
||||
// power failures
|
||||
|
||||
// sensor failures
|
||||
|
||||
////////////////////////////
|
||||
//
|
||||
// sub system failures
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef CONFIG_VALIDATOR
|
||||
#define CONFIG_VALIDATOR
|
||||
|
||||
#include "common/macros.h"
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef CONSTANTS_H
|
||||
#define CONSTANTS_H
|
||||
|
||||
#include "enums.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Addons
|
||||
//
|
||||
|
||||
#define CURRENT_SENSOR_STR "CurrentSensor"
|
||||
#define ENCLOSURE_SENSOR_STR "EnclosureSensor"
|
||||
#define POWER_STR "Power"
|
||||
#define OPERATION_MODE_SWITCH_STR "OperationModeSwitch"
|
||||
#define APP_STR "App"
|
||||
#define STATUS_STR "Status LED"
|
||||
#define MPID_CTRL_STR "Multi - PID Controller"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,89 @@
|
||||
#ifndef ENUMS_H
|
||||
#define ENUMS_H
|
||||
|
||||
enum PIN_TYPE
|
||||
{
|
||||
ANALOG,
|
||||
DIGITAL
|
||||
};
|
||||
|
||||
enum BOARD
|
||||
{
|
||||
UNO,
|
||||
MEGA
|
||||
};
|
||||
|
||||
enum PARTITION_STATE
|
||||
{
|
||||
OFF = 0,
|
||||
HEATING = 1
|
||||
AUTO_TUNING = 2,
|
||||
AUTO = 3,
|
||||
DISABLED = 4,
|
||||
ERROR = 10
|
||||
};
|
||||
|
||||
enum CONTROL_MODE
|
||||
{
|
||||
OP_PANEL = 1, // OLED & Keypad
|
||||
EXTERN = 2 // RS485
|
||||
};
|
||||
|
||||
enum RUN_MODE
|
||||
{
|
||||
PID = 0, // Normal PID mode
|
||||
MANUAL = 1, // Debugging / Operator
|
||||
TEST = 2, // Run remote tests
|
||||
ERROR = 3
|
||||
LOCKED = 4
|
||||
};
|
||||
|
||||
enum ADDON_FLAGS
|
||||
{
|
||||
DEBUG = 1,
|
||||
INFO = 2,
|
||||
LOOP = 3,
|
||||
DISABLED = 4,
|
||||
SETUP = 5,
|
||||
MAIN = 6,
|
||||
STATE = 7
|
||||
};
|
||||
|
||||
enum ADDONS
|
||||
{
|
||||
ENCLOSURE_SENSOR = 6,
|
||||
DIP_SWITCH = 10,
|
||||
POWER = 11,
|
||||
OPERATION_MODE_SWITCH = 20,
|
||||
SERIAL_BRIDGE = 23,
|
||||
APP = 25,
|
||||
MODBUS_BRIDGE = 26,
|
||||
CURRENT_SENSOR = 32,
|
||||
STATUS = 33,
|
||||
MPIDCTRL = 34,
|
||||
LAST = 64
|
||||
};
|
||||
|
||||
enum POWER_CIRCUIT
|
||||
{
|
||||
POWER_1 = 0,
|
||||
POWER_2 = 1,
|
||||
POWER_3 = 1
|
||||
};
|
||||
|
||||
enum OPERATION_MODE
|
||||
{
|
||||
OP_NONE = 0,
|
||||
OP_NORMAL = 1,
|
||||
OP_DEBUG = 2,
|
||||
OP_SERVICE = 3,
|
||||
OP_TEST
|
||||
};
|
||||
enum ERROR
|
||||
{
|
||||
ERROR_OK = 0,
|
||||
ERROR_WARNING = 1,
|
||||
ERROR_FATAL = 2
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef FEATURES_H
|
||||
#define FEATURES_H
|
||||
|
||||
#ifdef HAS_RESET
|
||||
#include "reset.h"
|
||||
#endif
|
||||
|
||||
#include "addons/CurrentSensor.h"
|
||||
|
||||
#ifdef HAS_STATUS
|
||||
#include "addons/Status.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "app.h"
|
||||
|
||||
App app = App();
|
||||
|
||||
void setup(){
|
||||
app.setup();
|
||||
app.info();
|
||||
Serial.println("------------------ Ready -------------------------------------- ");
|
||||
}
|
||||
void loop(){
|
||||
app.loop();
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "@plastichub/pid-firmware",
|
||||
"version": "0.1",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"cid": 0,
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/plastic-hub/firmware.git"
|
||||
},
|
||||
"keywords": [
|
||||
"precious",
|
||||
"plastic"
|
||||
],
|
||||
"author": "PlasticHUB",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"bugs": {
|
||||
"url": "https://github.com/plastic-hub/firmware/issues"
|
||||
},
|
||||
"homepage": "https://github.com/plastic-hub/firmware#readme",
|
||||
"dependencies": {
|
||||
"@xblox/fs": "^0.13.19",
|
||||
"simple-git": "^1.131.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
#include "ppmath_statistics.h"
|
||||
|
||||
Statistic::Statistic()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
// resets all counters
|
||||
void Statistic::clear()
|
||||
{
|
||||
_cnt = 0;
|
||||
_sum = 0;
|
||||
_min = 0;
|
||||
_max = 0;
|
||||
#ifdef STAT_USE_STDEV
|
||||
_ssqdif = 0.0; // not _ssq but sum of square differences
|
||||
// which is SUM(from i = 1 to N) of
|
||||
// (f(i)-_ave_N)**2
|
||||
#endif
|
||||
}
|
||||
|
||||
// adds a new value to the data-set
|
||||
void Statistic::add(const float value)
|
||||
{
|
||||
if (_cnt == 0)
|
||||
{
|
||||
_min = value;
|
||||
_max = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (value < _min)
|
||||
_min = value;
|
||||
else if (value > _max)
|
||||
_max = value;
|
||||
}
|
||||
_sum += value;
|
||||
_cnt++;
|
||||
|
||||
#ifdef STAT_USE_STDEV
|
||||
if (_cnt > 1)
|
||||
{
|
||||
float _store = (_sum / _cnt - value);
|
||||
_ssqdif = _ssqdif + _cnt * _store * _store / (_cnt - 1);
|
||||
// ~10% faster but limits the amount of samples to 65K as _cnt*_cnt overflows
|
||||
// float _store = _sum - _cnt * value;
|
||||
// _ssqdif = _ssqdif + _store * _store / (_cnt*_cnt - _cnt);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// returns the average of the data-set added sofar
|
||||
float Statistic::average() const
|
||||
{
|
||||
if (_cnt == 0)
|
||||
return NAN; // original code returned 0
|
||||
return _sum / _cnt;
|
||||
}
|
||||
|
||||
// Population standard deviation = s = sqrt [ S ( Xi - � )2 / N ]
|
||||
// http://www.suite101.com/content/how-is-standard-deviation-used-a99084
|
||||
#ifdef STAT_USE_STDEV
|
||||
|
||||
float Statistic::variance() const
|
||||
{
|
||||
if (_cnt == 0)
|
||||
return NAN; // otherwise DIV0 error
|
||||
return _ssqdif / _cnt;
|
||||
}
|
||||
|
||||
float Statistic::mean() const
|
||||
{
|
||||
if (_cnt == 0)
|
||||
return NAN; // otherwise DIV0 error
|
||||
return this->sum() / _cnt;
|
||||
}
|
||||
|
||||
float Statistic::pop_stdev() const
|
||||
{
|
||||
if (_cnt == 0)
|
||||
return NAN; // otherwise DIV0 error
|
||||
return sqrt(_ssqdif / _cnt);
|
||||
}
|
||||
|
||||
float Statistic::unbiased_stdev() const
|
||||
{
|
||||
if (_cnt < 2)
|
||||
return NAN; // otherwise DIV0 error
|
||||
return sqrt(_ssqdif / (_cnt - 1));
|
||||
}
|
||||
|
||||
#endif
|
||||
// END OF FILE
|
||||
@@ -0,0 +1,116 @@
|
||||
#ifndef PPMATH_STATISTICS_H
|
||||
#define PPMATH_STATISTICS_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <math.h>
|
||||
|
||||
#define STAT_USE_STDEV
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
// C++11 solution that is standards compliant. Return type is deduced automatically
|
||||
template <class L, class R>
|
||||
static inline constexpr auto MIN(const L lhs, const R rhs) -> decltype(lhs + rhs)
|
||||
{
|
||||
return lhs < rhs ? lhs : rhs;
|
||||
}
|
||||
template <class L, class R>
|
||||
static inline constexpr auto MAX(const L lhs, const R rhs) -> decltype(lhs + rhs)
|
||||
{
|
||||
return lhs > rhs ? lhs : rhs;
|
||||
}
|
||||
template <class T>
|
||||
static inline constexpr const T ABS(const T v)
|
||||
{
|
||||
return v >= 0 ? v : -v;
|
||||
}
|
||||
#else
|
||||
// Using GCC extensions, but Travis GCC version does not like it and gives
|
||||
// "error: statement-expressions are not allowed outside functions nor in template-argument lists"
|
||||
#define MIN(a, b) \
|
||||
({__typeof__(a) _a = (a); \
|
||||
__typeof__(b) _b = (b); \
|
||||
_a < _b ? _a : _b; })
|
||||
|
||||
#define MAX(a, b) \
|
||||
({__typeof__(a) _a = (a); \
|
||||
__typeof__(b) _b = (b); \
|
||||
_a > _b ? _a : _b; })
|
||||
|
||||
#define ABS(a) \
|
||||
({__typeof__(a) _a = (a); \
|
||||
_a >= 0 ? _a : -_a; })
|
||||
|
||||
#endif
|
||||
|
||||
class Statistic
|
||||
{
|
||||
public:
|
||||
Statistic(); // "switches on/off" stdev run time
|
||||
void clear(); // "switches on/off" stdev run time
|
||||
void add(const float);
|
||||
|
||||
// returns the number of values added
|
||||
uint32_t count() const { return _cnt; }; // zero if empty
|
||||
float sum() const { return _sum; }; // zero if empty
|
||||
float minimum() const { return _min; }; // zero if empty
|
||||
float maximum() const { return _max; }; // zero if empty
|
||||
float average() const; // NAN if empty
|
||||
float mean() const; // zero if empty
|
||||
|
||||
#ifdef STAT_USE_STDEV
|
||||
float variance() const; // NAN if empty
|
||||
float pop_stdev() const; // population stdev // NAN if empty
|
||||
float unbiased_stdev() const; // NAN if empty
|
||||
#endif
|
||||
|
||||
protected:
|
||||
uint32_t _cnt;
|
||||
float _sum;
|
||||
float _min;
|
||||
float _max;
|
||||
#ifdef STAT_USE_STDEV
|
||||
float _ssqdif; // sum of squares difference
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the kth q-quantile.
|
||||
* @link http://en.wikipedia.org/wiki/Quantile#Quantiles_of_a_population
|
||||
* ie: median is 1st 2-quantile
|
||||
* ie: upper quartile is 3rd 4-quantile
|
||||
* @return {Number} q-quantile of values.
|
||||
*/
|
||||
/*
|
||||
const quantile = (arr: number[], i: number, n: number) => {
|
||||
if (i === 0) return Math.min.apply(null, arr);
|
||||
if (i === n) return Math.max.apply(null, arr);
|
||||
|
||||
let sorted = arr.slice(0);
|
||||
sorted.sort((a, b) => a - b);
|
||||
let index = sorted.length * i / n;
|
||||
|
||||
if (index % 1 === 0) {
|
||||
return 0.5 * sorted[index - 1] + 0.5 * sorted[index];
|
||||
}
|
||||
|
||||
return sorted[~~index];
|
||||
};
|
||||
|
||||
export const median = (arr: number[]) => quantile(arr, 1, 2);
|
||||
|
||||
export const sum = (arr: number[]) => arr.reduce((a, b) => a + b, 0);
|
||||
|
||||
export const mean = (arr: number[]) => sum(arr) / arr.length;
|
||||
|
||||
|
||||
// sqare errors along mean
|
||||
const sdiff = (arr: number[], mean: number) => arr.map((v) =>
|
||||
Math.pow(v - mean, 2)
|
||||
);
|
||||
|
||||
export const standardDeviation = (arr: number[]) =>
|
||||
Math.sqrt(mean(sdiff(arr, mean(arr))));
|
||||
*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef TYPES_H
|
||||
#define TYPES_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef unsigned long millis_t;
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned char uchar;
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,4 @@
|
||||
#ifndef USER_CONFIG_H
|
||||
#define USER_CONFIG_H
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
@file
|
||||
CRC Computations
|
||||
|
||||
@defgroup util_crc16 "util/crc16.h": CRC Computations
|
||||
@code#include "util/crc16.h"@endcode
|
||||
|
||||
This header file provides functions for calculating
|
||||
cyclic redundancy checks (CRC) using common polynomials.
|
||||
Modified by Doc Walker to be processor-independent (removed inline
|
||||
assembler to allow it to compile on SAM3X8E processors).
|
||||
|
||||
@par References:
|
||||
Jack Crenshaw's "Implementing CRCs" article in the January 1992 issue of @e
|
||||
Embedded @e Systems @e Programming. This may be difficult to find, but it
|
||||
explains CRC's in very clear and concise terms. Well worth the effort to
|
||||
obtain a copy.
|
||||
|
||||
*/
|
||||
/* Copyright (c) 2002, 2003, 2004 Marek Michalkiewicz
|
||||
Copyright (c) 2005, 2007 Joerg Wunsch
|
||||
Copyright (c) 2013 Dave Hylands
|
||||
Copyright (c) 2013 Frederic Nadeau
|
||||
Copyright (c) 2015 Doc Walker
|
||||
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.
|
||||
|
||||
* Neither the name of the copyright holders nor the names of
|
||||
contributors may 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 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. */
|
||||
|
||||
|
||||
#ifndef _UTIL_CRC16_H_
|
||||
#define _UTIL_CRC16_H_
|
||||
|
||||
|
||||
/** @ingroup util_crc16
|
||||
Processor-independent CRC-16 calculation.
|
||||
|
||||
Polynomial: x^16 + x^15 + x^2 + 1 (0xA001)<br>
|
||||
Initial value: 0xFFFF
|
||||
|
||||
This CRC is normally used in disk-drive controllers.
|
||||
|
||||
@param uint16_t crc (0x0000..0xFFFF)
|
||||
@param uint8_t a (0x00..0xFF)
|
||||
@return calculated CRC (0x0000..0xFFFF)
|
||||
*/
|
||||
uint16_t crc16_update(uint16_t crc, uint8_t a);
|
||||
/*{
|
||||
int i;
|
||||
|
||||
crc ^= a;
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
if (crc & 1)
|
||||
crc = (crc >> 1) ^ 0xA001;
|
||||
else
|
||||
crc = (crc >> 1);
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
*/
|
||||
|
||||
#endif /* _UTIL_CRC16_H_ */
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
@file
|
||||
Utility Functions for Manipulating Words
|
||||
|
||||
@defgroup util_word "util/word.h": Utility Functions for Manipulating Words
|
||||
@code#include "util/word.h"@endcode
|
||||
|
||||
This header file provides utility functions for manipulating words.
|
||||
|
||||
*/
|
||||
/*
|
||||
|
||||
word.h - Utility Functions for Manipulating Words
|
||||
|
||||
This file is part of ModbusMaster.
|
||||
|
||||
ModbusMaster 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.
|
||||
|
||||
ModbusMaster 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 ModbusMaster. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Written by Doc Walker (Rx)
|
||||
Copyright © 2009-2015 Doc Walker <4-20ma at wvfans dot net>
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _UTIL_WORD_H_
|
||||
#define _UTIL_WORD_H_
|
||||
|
||||
|
||||
/** @ingroup util_word
|
||||
Return low word of a 32-bit integer.
|
||||
|
||||
@param uint32_t ww (0x00000000..0xFFFFFFFF)
|
||||
@return low word of input (0x0000..0xFFFF)
|
||||
*/
|
||||
static inline uint16_t lowWord(uint32_t ww)
|
||||
{
|
||||
return (uint16_t) ((ww) & 0xFFFF);
|
||||
}
|
||||
|
||||
|
||||
/** @ingroup util_word
|
||||
Return high word of a 32-bit integer.
|
||||
|
||||
@param uint32_t ww (0x00000000..0xFFFFFFFF)
|
||||
@return high word of input (0x0000..0xFFFF)
|
||||
*/
|
||||
static inline uint16_t highWord(uint32_t ww)
|
||||
{
|
||||
return (uint16_t) ((ww) >> 16);
|
||||
}
|
||||
|
||||
|
||||
#endif /* _UTIL_WORD_H_ */
|
||||
@@ -0,0 +1,34 @@
|
||||
const read = require('@xblox/fs/read');
|
||||
const write = require('@xblox/fs/write');
|
||||
const path = require('path');
|
||||
const cwd = path.resolve('../../');
|
||||
const pkgVersion = read.sync('package.json', 'json').version;
|
||||
const cid = read.sync('package.json', 'json').cid;
|
||||
|
||||
async function status(workingDir) {
|
||||
const git = require('simple-git/promise');
|
||||
|
||||
let statusSummary = null;
|
||||
try {
|
||||
statusSummary = await git(workingDir).log();
|
||||
}
|
||||
catch (e) {
|
||||
// handle the error
|
||||
}
|
||||
|
||||
return statusSummary;
|
||||
}
|
||||
|
||||
|
||||
status(cwd).then((status) => {
|
||||
const version =
|
||||
`#ifndef VERSION_H \n
|
||||
#define VERSION_H \n
|
||||
#define VERSION "${pkgVersion}|${status.latest.hash}"\n
|
||||
#define CID "${cid}"\n
|
||||
#endif`;
|
||||
|
||||
write.sync('./Version.h', version);
|
||||
console.log(version);
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,788 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@sindresorhus/df@^1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@sindresorhus/df/-/df-1.0.1.tgz#c69b66f52f6fcdd287c807df210305dbaf78500d"
|
||||
integrity sha1-xptm9S9vzdKHyAffIQMF2694UA0=
|
||||
|
||||
"@sindresorhus/df@^2.1.0":
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@sindresorhus/df/-/df-2.1.0.tgz#d208cf27e06f0bb476d14d7deccd7d726e9aa389"
|
||||
integrity sha1-0gjPJ+BvC7R20U197M19cm6ao4k=
|
||||
dependencies:
|
||||
execa "^0.2.2"
|
||||
|
||||
"@types/minimatch@^3.0.3":
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
|
||||
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
|
||||
|
||||
"@xblox/core@0.0.18":
|
||||
version "0.0.18"
|
||||
resolved "https://registry.yarnpkg.com/@xblox/core/-/core-0.0.18.tgz#6513807ba2982c6b274b3e3972bec312dfb2c8da"
|
||||
integrity sha1-ZROAe6KYLGsnSz45cr7DEt+yyNo=
|
||||
dependencies:
|
||||
base-64 "^0.1.0"
|
||||
jsonpath "^0.2.11"
|
||||
qs "^6.4.0"
|
||||
reflect-metadata "^0.1.10"
|
||||
|
||||
"@xblox/fs@^0.13.19":
|
||||
version "0.13.19"
|
||||
resolved "https://registry.yarnpkg.com/@xblox/fs/-/fs-0.13.19.tgz#7231ac9bc186a15a48d04a9c4d86c7ff651f8740"
|
||||
integrity sha512-211yh3Zkm0AIMjNfhOhGzw+vTWH+O4zMivktjW0M+l5mJkyM2f92Pw/GBvxFAOWR2Fryn2NfCIF1GiQIRYdTEQ==
|
||||
dependencies:
|
||||
"@types/minimatch" "^3.0.3"
|
||||
"@xblox/core" "0.0.18"
|
||||
denodeify "^1.2.1"
|
||||
errno "^0.1.4"
|
||||
mime "^2.0.3"
|
||||
minimatch "^3.0.4"
|
||||
mkdirp "^0.5.1"
|
||||
progress-stream "^1.2.0"
|
||||
q "^1.4.1"
|
||||
rimraf "^2.6.2"
|
||||
throttle "^1.0.3"
|
||||
trash "^4.0.1"
|
||||
write-file-atomic "^1.3.1"
|
||||
|
||||
JSONSelect@0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/JSONSelect/-/JSONSelect-0.4.0.tgz#a08edcc67eb3fcbe99ed630855344a0cf282bb8d"
|
||||
integrity sha1-oI7cxn6z/L6Z7WMIVTRKDPKCu40=
|
||||
|
||||
array-union@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
|
||||
integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=
|
||||
dependencies:
|
||||
array-uniq "^1.0.1"
|
||||
|
||||
array-uniq@^1.0.1:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
|
||||
integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
|
||||
|
||||
base-64@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/base-64/-/base-64-0.1.0.tgz#780a99c84e7d600260361511c4877613bf24f6bb"
|
||||
integrity sha1-eAqZyE59YAJgNhURxId2E78k9rs=
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
|
||||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
concat-map "0.0.1"
|
||||
|
||||
cjson@~0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/cjson/-/cjson-0.2.1.tgz#73cd8aad65d9e1505f9af1744d3b79c1527682a5"
|
||||
integrity sha1-c82KrWXZ4VBfmvF0TTt5wVJ2gqU=
|
||||
|
||||
colors@0.5.x:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/colors/-/colors-0.5.1.tgz#7d0023eaeb154e8ee9fce75dcb923d0ed1667774"
|
||||
integrity sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q=
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||
|
||||
core-util-is@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||
|
||||
cross-spawn-async@^2.1.1:
|
||||
version "2.2.5"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz#845ff0c0834a3ded9d160daca6d390906bb288cc"
|
||||
integrity sha1-hF/wwINKPe2dFg2sptOQkGuyiMw=
|
||||
dependencies:
|
||||
lru-cache "^4.0.0"
|
||||
which "^1.2.8"
|
||||
|
||||
cross-spawn@^6.0.0:
|
||||
version "6.0.5"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
|
||||
integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
|
||||
dependencies:
|
||||
nice-try "^1.0.4"
|
||||
path-key "^2.0.1"
|
||||
semver "^5.5.0"
|
||||
shebang-command "^1.2.0"
|
||||
which "^1.2.9"
|
||||
|
||||
debug@2:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@^4.0.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
|
||||
integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
denodeify@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631"
|
||||
integrity sha1-OjYof1A05pnnV3kBBSwubJQlFjE=
|
||||
|
||||
dir-glob@^2.0.0:
|
||||
version "2.2.2"
|
||||
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4"
|
||||
integrity sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==
|
||||
dependencies:
|
||||
path-type "^3.0.0"
|
||||
|
||||
ebnf-parser@~0.1.9:
|
||||
version "0.1.10"
|
||||
resolved "https://registry.yarnpkg.com/ebnf-parser/-/ebnf-parser-0.1.10.tgz#cd1f6ba477c5638c40c97ed9b572db5bab5d8331"
|
||||
integrity sha1-zR9rpHfFY4xAyX7ZtXLbW6tdgzE=
|
||||
|
||||
errno@^0.1.4:
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618"
|
||||
integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==
|
||||
dependencies:
|
||||
prr "~1.0.1"
|
||||
|
||||
escape-string-applescript@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/escape-string-applescript/-/escape-string-applescript-2.0.0.tgz#760bca838668e408fe5ee52ce42caf7cb46c5273"
|
||||
integrity sha1-dgvKg4Zo5Aj+XuUs5CyvfLRsUnM=
|
||||
|
||||
escodegen@0.0.21:
|
||||
version "0.0.21"
|
||||
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-0.0.21.tgz#53d652cfa1030388279458a5266c5ffc709c63c3"
|
||||
integrity sha1-U9ZSz6EDA4gnlFilJmxf/HCcY8M=
|
||||
dependencies:
|
||||
esprima "~1.0.2"
|
||||
estraverse "~0.0.4"
|
||||
optionalDependencies:
|
||||
source-map ">= 0.1.2"
|
||||
|
||||
escodegen@~0.0.24:
|
||||
version "0.0.28"
|
||||
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-0.0.28.tgz#0e4ff1715f328775d6cab51ac44a406cd7abffd3"
|
||||
integrity sha1-Dk/xcV8yh3XWyrUaxEpAbNer/9M=
|
||||
dependencies:
|
||||
esprima "~1.0.2"
|
||||
estraverse "~1.3.0"
|
||||
optionalDependencies:
|
||||
source-map ">= 0.1.2"
|
||||
|
||||
esprima@1.0.x, esprima@~1.0.2:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.0.4.tgz#9f557e08fc3b4d26ece9dd34f8fbf476b62585ad"
|
||||
integrity sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=
|
||||
|
||||
esprima@1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.2.2.tgz#76a0fd66fcfe154fd292667dc264019750b1657b"
|
||||
integrity sha1-dqD9Zvz+FU/SkmZ9wmQBl1CxZXs=
|
||||
|
||||
estraverse@~0.0.4:
|
||||
version "0.0.4"
|
||||
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-0.0.4.tgz#01a0932dfee574684a598af5a67c3bf9b6428db2"
|
||||
integrity sha1-AaCTLf7ldGhKWYr1pnw7+bZCjbI=
|
||||
|
||||
estraverse@~1.3.0:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.3.2.tgz#37c2b893ef13d723f276d878d60d8535152a6c42"
|
||||
integrity sha1-N8K4k+8T1yPydth41g2FNRUqbEI=
|
||||
|
||||
execa@^0.10.0:
|
||||
version "0.10.0"
|
||||
resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50"
|
||||
integrity sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==
|
||||
dependencies:
|
||||
cross-spawn "^6.0.0"
|
||||
get-stream "^3.0.0"
|
||||
is-stream "^1.1.0"
|
||||
npm-run-path "^2.0.0"
|
||||
p-finally "^1.0.0"
|
||||
signal-exit "^3.0.0"
|
||||
strip-eof "^1.0.0"
|
||||
|
||||
execa@^0.2.2:
|
||||
version "0.2.2"
|
||||
resolved "https://registry.yarnpkg.com/execa/-/execa-0.2.2.tgz#e2ead472c2c31aad6f73f1ac956eef45e12320cb"
|
||||
integrity sha1-4urUcsLDGq1vc/GslW7vReEjIMs=
|
||||
dependencies:
|
||||
cross-spawn-async "^2.1.1"
|
||||
npm-run-path "^1.0.0"
|
||||
object-assign "^4.0.1"
|
||||
path-key "^1.0.0"
|
||||
strip-eof "^1.0.0"
|
||||
|
||||
fs-extra@^0.30.0:
|
||||
version "0.30.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0"
|
||||
integrity sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=
|
||||
dependencies:
|
||||
graceful-fs "^4.1.2"
|
||||
jsonfile "^2.1.0"
|
||||
klaw "^1.0.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
rimraf "^2.2.8"
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
|
||||
|
||||
get-stream@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
|
||||
integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=
|
||||
|
||||
glob@^7.1.2, glob@^7.1.3:
|
||||
version "7.1.6"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
|
||||
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.0.4"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
globby@^7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/globby/-/globby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680"
|
||||
integrity sha1-+yzP+UAfhgCUXfral0QMypcrhoA=
|
||||
dependencies:
|
||||
array-union "^1.0.1"
|
||||
dir-glob "^2.0.0"
|
||||
glob "^7.1.2"
|
||||
ignore "^3.3.5"
|
||||
pify "^3.0.0"
|
||||
slash "^1.0.0"
|
||||
|
||||
graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9:
|
||||
version "4.2.4"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
|
||||
integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
|
||||
|
||||
ignore@^3.3.5:
|
||||
version "3.3.10"
|
||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043"
|
||||
integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==
|
||||
|
||||
imurmurhash@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
||||
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
|
||||
|
||||
inflight@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||
integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
|
||||
dependencies:
|
||||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2, inherits@^2.0.3, inherits@~2.0.1:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
||||
is-stream@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
|
||||
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
|
||||
|
||||
isarray@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
|
||||
integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
|
||||
|
||||
isexe@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||
integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
|
||||
|
||||
jison-lex@0.2.x:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/jison-lex/-/jison-lex-0.2.1.tgz#ac4b815e8cce5132eb12b5dfcfe8d707b8844dfe"
|
||||
integrity sha1-rEuBXozOUTLrErXfz+jXB7iETf4=
|
||||
dependencies:
|
||||
lex-parser "0.1.x"
|
||||
nomnom "1.5.2"
|
||||
|
||||
jison@0.4.13:
|
||||
version "0.4.13"
|
||||
resolved "https://registry.yarnpkg.com/jison/-/jison-0.4.13.tgz#9041707d62241367f58834532b9f19c2c36fac78"
|
||||
integrity sha1-kEFwfWIkE2f1iDRTK58ZwsNvrHg=
|
||||
dependencies:
|
||||
JSONSelect "0.4.0"
|
||||
cjson "~0.2.1"
|
||||
ebnf-parser "~0.1.9"
|
||||
escodegen "0.0.21"
|
||||
esprima "1.0.x"
|
||||
jison-lex "0.2.x"
|
||||
lex-parser "~0.1.3"
|
||||
nomnom "1.5.2"
|
||||
|
||||
jsonfile@^2.1.0:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8"
|
||||
integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug=
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
jsonpath@^0.2.11:
|
||||
version "0.2.12"
|
||||
resolved "https://registry.yarnpkg.com/jsonpath/-/jsonpath-0.2.12.tgz#5bf9d911fb4616c1e3370beceb9f0db24ae34cd2"
|
||||
integrity sha1-W/nZEftGFsHjNwvs658NskrjTNI=
|
||||
dependencies:
|
||||
esprima "1.2.2"
|
||||
jison "0.4.13"
|
||||
static-eval "0.2.3"
|
||||
underscore "1.7.0"
|
||||
|
||||
klaw@^1.0.0:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439"
|
||||
integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk=
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.9"
|
||||
|
||||
lex-parser@0.1.x, lex-parser@~0.1.3:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/lex-parser/-/lex-parser-0.1.4.tgz#64c4f025f17fd53bfb45763faeb16f015a747550"
|
||||
integrity sha1-ZMTwJfF/1Tv7RXY/rrFvAVp0dVA=
|
||||
|
||||
lru-cache@^4.0.0:
|
||||
version "4.1.5"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
|
||||
integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
|
||||
dependencies:
|
||||
pseudomap "^1.0.2"
|
||||
yallist "^2.1.2"
|
||||
|
||||
mime@^2.0.3:
|
||||
version "2.4.5"
|
||||
resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.5.tgz#d8de2ecb92982dedbb6541c9b6841d7f218ea009"
|
||||
integrity sha512-3hQhEUF027BuxZjQA3s7rIv/7VCQPa27hN9u9g87sEkWaKwQPuXOkVKtOeiyUrnWqTDiOs8Ed2rwg733mB0R5w==
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@^1.2.5:
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
||||
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
||||
|
||||
mkdirp@^0.5.1:
|
||||
version "0.5.5"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
|
||||
integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
|
||||
dependencies:
|
||||
minimist "^1.2.5"
|
||||
|
||||
mount-point@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mount-point/-/mount-point-3.0.0.tgz#665cb9edebe80d110e658db56c31d0aef51a8f97"
|
||||
integrity sha1-Zly57evoDREOZY21bDHQrvUaj5c=
|
||||
dependencies:
|
||||
"@sindresorhus/df" "^1.0.1"
|
||||
pify "^2.3.0"
|
||||
pinkie-promise "^2.0.1"
|
||||
|
||||
ms@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
|
||||
|
||||
ms@^2.1.1:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
nice-try@^1.0.4:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
||||
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
|
||||
|
||||
nomnom@1.5.2:
|
||||
version "1.5.2"
|
||||
resolved "https://registry.yarnpkg.com/nomnom/-/nomnom-1.5.2.tgz#f4345448a853cfbd5c0d26320f2477ab0526fe2f"
|
||||
integrity sha1-9DRUSKhTz71cDSYyDyR3qwUm/i8=
|
||||
dependencies:
|
||||
colors "0.5.x"
|
||||
underscore "1.1.x"
|
||||
|
||||
npm-run-path@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-1.0.0.tgz#f5c32bf595fe81ae927daec52e82f8b000ac3c8f"
|
||||
integrity sha1-9cMr9ZX+ga6Sfa7FLoL4sACsPI8=
|
||||
dependencies:
|
||||
path-key "^1.0.0"
|
||||
|
||||
npm-run-path@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
|
||||
integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=
|
||||
dependencies:
|
||||
path-key "^2.0.0"
|
||||
|
||||
object-assign@^4.0.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
|
||||
object-keys@~0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336"
|
||||
integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=
|
||||
|
||||
once@^1.3.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
|
||||
dependencies:
|
||||
wrappy "1"
|
||||
|
||||
os-homedir@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
|
||||
integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
|
||||
|
||||
p-finally@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
|
||||
integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
|
||||
|
||||
p-map@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b"
|
||||
integrity sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==
|
||||
|
||||
p-try@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
|
||||
integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=
|
||||
|
||||
path-is-absolute@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
|
||||
|
||||
path-key@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/path-key/-/path-key-1.0.0.tgz#5d53d578019646c0d68800db4e146e6bdc2ac7af"
|
||||
integrity sha1-XVPVeAGWRsDWiADbThRua9wqx68=
|
||||
|
||||
path-key@^2.0.0, path-key@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
|
||||
integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
|
||||
|
||||
path-type@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
|
||||
integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==
|
||||
dependencies:
|
||||
pify "^3.0.0"
|
||||
|
||||
pify@^2.2.0, pify@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
|
||||
integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
|
||||
|
||||
pify@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
|
||||
integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
|
||||
|
||||
pinkie-promise@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
|
||||
integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o=
|
||||
dependencies:
|
||||
pinkie "^2.0.0"
|
||||
|
||||
pinkie@^2.0.0:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
|
||||
integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
|
||||
|
||||
progress-stream@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/progress-stream/-/progress-stream-1.2.0.tgz#2cd3cfea33ba3a89c9c121ec3347abe9ab125f77"
|
||||
integrity sha1-LNPP6jO6OonJwSHsM0er6asSX3c=
|
||||
dependencies:
|
||||
speedometer "~0.1.2"
|
||||
through2 "~0.2.3"
|
||||
|
||||
prr@~1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
|
||||
integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY=
|
||||
|
||||
pseudomap@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
|
||||
integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
|
||||
|
||||
q@^1.4.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
|
||||
integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
|
||||
|
||||
qs@^6.4.0:
|
||||
version "6.9.3"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.3.tgz#bfadcd296c2d549f1dffa560619132c977f5008e"
|
||||
integrity sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw==
|
||||
|
||||
"readable-stream@>= 0.3.0":
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
|
||||
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
|
||||
dependencies:
|
||||
inherits "^2.0.3"
|
||||
string_decoder "^1.1.1"
|
||||
util-deprecate "^1.0.1"
|
||||
|
||||
readable-stream@~1.1.9:
|
||||
version "1.1.14"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
|
||||
integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk=
|
||||
dependencies:
|
||||
core-util-is "~1.0.0"
|
||||
inherits "~2.0.1"
|
||||
isarray "0.0.1"
|
||||
string_decoder "~0.10.x"
|
||||
|
||||
reflect-metadata@^0.1.10:
|
||||
version "0.1.13"
|
||||
resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08"
|
||||
integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==
|
||||
|
||||
rimraf@^2.2.8, rimraf@^2.6.2:
|
||||
version "2.7.1"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
|
||||
integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
|
||||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
run-applescript@^3.0.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-3.2.0.tgz#73fb34ce85d3de8076d511ea767c30d4fdfc918b"
|
||||
integrity sha512-Ep0RsvAjnRcBX1p5vogbaBdAGu/8j/ewpvGqnQYunnLd9SM0vWcPJewPKNnWFggf0hF0pwIgwV5XK7qQ7UZ8Qg==
|
||||
dependencies:
|
||||
execa "^0.10.0"
|
||||
|
||||
safe-buffer@~5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519"
|
||||
integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==
|
||||
|
||||
semver@^5.5.0:
|
||||
version "5.7.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||
|
||||
shebang-command@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
|
||||
integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=
|
||||
dependencies:
|
||||
shebang-regex "^1.0.0"
|
||||
|
||||
shebang-regex@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
|
||||
integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
|
||||
|
||||
signal-exit@^3.0.0:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
|
||||
integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
|
||||
|
||||
simple-git@^1.131.0:
|
||||
version "1.132.0"
|
||||
resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-1.132.0.tgz#53ac4c5ec9e74e37c2fd461e23309f22fcdf09b1"
|
||||
integrity sha512-xauHm1YqCTom1sC9eOjfq3/9RKiUA9iPnxBbrY2DdL8l4ADMu0jjM5l5lphQP5YWNqAL2aXC/OeuQ76vHtW5fg==
|
||||
dependencies:
|
||||
debug "^4.0.1"
|
||||
|
||||
slash@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
|
||||
integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=
|
||||
|
||||
slide@^1.1.5:
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707"
|
||||
integrity sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=
|
||||
|
||||
"source-map@>= 0.1.2":
|
||||
version "0.7.3"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
|
||||
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
|
||||
|
||||
speedometer@~0.1.2:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/speedometer/-/speedometer-0.1.4.tgz#9876dbd2a169d3115402d48e6ea6329c8816a50d"
|
||||
integrity sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=
|
||||
|
||||
static-eval@0.2.3:
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-0.2.3.tgz#023f17ac9fee426ea788c12ea39206dc175f8b2a"
|
||||
integrity sha1-Aj8XrJ/uQm6niMEuo5IG3Bdfiyo=
|
||||
dependencies:
|
||||
escodegen "~0.0.24"
|
||||
|
||||
"stream-parser@>= 0.0.2":
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/stream-parser/-/stream-parser-0.3.1.tgz#1618548694420021a1182ff0af1911c129761773"
|
||||
integrity sha1-FhhUhpRCACGhGC/wrxkRwSl2F3M=
|
||||
dependencies:
|
||||
debug "2"
|
||||
|
||||
string_decoder@^1.1.1:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
|
||||
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
|
||||
dependencies:
|
||||
safe-buffer "~5.2.0"
|
||||
|
||||
string_decoder@~0.10.x:
|
||||
version "0.10.31"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
|
||||
integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
|
||||
|
||||
strip-eof@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
|
||||
integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
|
||||
|
||||
throttle@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/throttle/-/throttle-1.0.3.tgz#8a32e4a15f1763d997948317c5ebe3ad8a41e4b7"
|
||||
integrity sha1-ijLkoV8XY9mXlIMXxevjrYpB5Lc=
|
||||
dependencies:
|
||||
readable-stream ">= 0.3.0"
|
||||
stream-parser ">= 0.0.2"
|
||||
|
||||
through2@~0.2.3:
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/through2/-/through2-0.2.3.tgz#eb3284da4ea311b6cc8ace3653748a52abf25a3f"
|
||||
integrity sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=
|
||||
dependencies:
|
||||
readable-stream "~1.1.9"
|
||||
xtend "~2.1.1"
|
||||
|
||||
trash@^4.0.1:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/trash/-/trash-4.3.0.tgz#6ebeecdea4d666b06e389b47d135ea88e1de5075"
|
||||
integrity sha512-f36TKwIaBiXm63xSrn8OTNghg5CYHBsFVJvcObMo76LRpgariuRi2CqXQHw1VzfeximD0igdGaonOG6N760BtQ==
|
||||
dependencies:
|
||||
escape-string-applescript "^2.0.0"
|
||||
fs-extra "^0.30.0"
|
||||
globby "^7.1.1"
|
||||
p-map "^1.2.0"
|
||||
p-try "^1.0.0"
|
||||
pify "^3.0.0"
|
||||
run-applescript "^3.0.0"
|
||||
uuid "^3.1.0"
|
||||
xdg-trashdir "^2.1.1"
|
||||
|
||||
underscore@1.1.x:
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.1.7.tgz#40bab84bad19d230096e8d6ef628bff055d83db0"
|
||||
integrity sha1-QLq4S60Z0jAJbo1u9ii/8FXYPbA=
|
||||
|
||||
underscore@1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209"
|
||||
integrity sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=
|
||||
|
||||
user-home@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f"
|
||||
integrity sha1-nHC/2Babwdy/SGBODwS4tJzenp8=
|
||||
dependencies:
|
||||
os-homedir "^1.0.0"
|
||||
|
||||
util-deprecate@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
||||
|
||||
uuid@^3.1.0:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
|
||||
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
|
||||
|
||||
which@^1.2.8, which@^1.2.9:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
|
||||
integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
|
||||
dependencies:
|
||||
isexe "^2.0.0"
|
||||
|
||||
wrappy@1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
|
||||
|
||||
write-file-atomic@^1.3.1:
|
||||
version "1.3.4"
|
||||
resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f"
|
||||
integrity sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=
|
||||
dependencies:
|
||||
graceful-fs "^4.1.11"
|
||||
imurmurhash "^0.1.4"
|
||||
slide "^1.1.5"
|
||||
|
||||
xdg-basedir@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-2.0.0.tgz#edbc903cc385fc04523d966a335504b5504d1bd2"
|
||||
integrity sha1-7byQPMOF/ARSPZZqM1UEtVBNG9I=
|
||||
dependencies:
|
||||
os-homedir "^1.0.0"
|
||||
|
||||
xdg-trashdir@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/xdg-trashdir/-/xdg-trashdir-2.1.1.tgz#59a60aaf8e6f9240c1daed9a0944b2f514c27d8e"
|
||||
integrity sha512-KcVhPaOu2ZurYNHSRTf1+ZHORkTZGCQ+u0JHN17QixRISJq4pXOnjt/lQcehvtHL5QAKhSzKgyjrcNnPdkPBHA==
|
||||
dependencies:
|
||||
"@sindresorhus/df" "^2.1.0"
|
||||
mount-point "^3.0.0"
|
||||
pify "^2.2.0"
|
||||
user-home "^2.0.0"
|
||||
xdg-basedir "^2.0.0"
|
||||
|
||||
xtend@~2.1.1:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b"
|
||||
integrity sha1-bv7MKk2tjmlixJAbM3znuoe10os=
|
||||
dependencies:
|
||||
object-keys "~0.4.0"
|
||||
|
||||
yallist@^2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
|
||||
integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
|
||||
Reference in New Issue
Block a user