Dump from SVN
This commit is contained in:
BIN
firmware/lib/Adafruit-MCP23017-Arduino-Library-master.zip
Normal file
BIN
firmware/lib/Adafruit-MCP23017-Arduino-Library-master.zip
Normal file
Binary file not shown.
46
firmware/lib/Adafruit-MCP23017-Arduino-Library-master/.github/ISSUE_TEMPLATE.md
vendored
Normal file
46
firmware/lib/Adafruit-MCP23017-Arduino-Library-master/.github/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
Thank you for opening an issue on an Adafruit Arduino library repository. To
|
||||
improve the speed of resolution please review the following guidelines and
|
||||
common troubleshooting steps below before creating the issue:
|
||||
|
||||
- **Do not use GitHub issues for troubleshooting projects and issues.** Instead use
|
||||
the forums at http://forums.adafruit.com to ask questions and troubleshoot why
|
||||
something isn't working as expected. In many cases the problem is a common issue
|
||||
that you will more quickly receive help from the forum community. GitHub issues
|
||||
are meant for known defects in the code. If you don't know if there is a defect
|
||||
in the code then start with troubleshooting on the forum first.
|
||||
|
||||
- **If following a tutorial or guide be sure you didn't miss a step.** Carefully
|
||||
check all of the steps and commands to run have been followed. Consult the
|
||||
forum if you're unsure or have questions about steps in a guide/tutorial.
|
||||
|
||||
- **For Arduino projects check these very common issues to ensure they don't apply**:
|
||||
|
||||
- For uploading sketches or communicating with the board make sure you're using
|
||||
a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes
|
||||
very hard to tell the difference between a data and charge cable! Try using the
|
||||
cable with other devices or swapping to another cable to confirm it is not
|
||||
the problem.
|
||||
|
||||
- **Be sure you are supplying adequate power to the board.** Check the specs of
|
||||
your board and plug in an external power supply. In many cases just
|
||||
plugging a board into your computer is not enough to power it and other
|
||||
peripherals.
|
||||
|
||||
- **Double check all soldering joints and connections.** Flakey connections
|
||||
cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints.
|
||||
|
||||
- **Ensure you are using an official Arduino or Adafruit board.** We can't
|
||||
guarantee a clone board will have the same functionality and work as expected
|
||||
with this code and don't support them.
|
||||
|
||||
If you're sure this issue is a defect in the code and checked the steps above
|
||||
please fill in the following fields to provide enough troubleshooting information.
|
||||
You may delete the guideline and text above to just leave the following details:
|
||||
|
||||
- Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE**
|
||||
|
||||
- Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO
|
||||
VERSION HERE**
|
||||
|
||||
- List the steps to reproduce the problem below (if possible attach a sketch or
|
||||
copy the sketch code in too): **LIST REPRO STEPS BELOW**
|
26
firmware/lib/Adafruit-MCP23017-Arduino-Library-master/.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
26
firmware/lib/Adafruit-MCP23017-Arduino-Library-master/.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
Thank you for creating a pull request to contribute to Adafruit's GitHub code!
|
||||
Before you open the request please review the following guidelines and tips to
|
||||
help it be more easily integrated:
|
||||
|
||||
- **Describe the scope of your change--i.e. what the change does and what parts
|
||||
of the code were modified.** This will help us understand any risks of integrating
|
||||
the code.
|
||||
|
||||
- **Describe any known limitations with your change.** For example if the change
|
||||
doesn't apply to a supported platform of the library please mention it.
|
||||
|
||||
- **Please run any tests or examples that can exercise your modified code.** We
|
||||
strive to not break users of the code and running tests/examples helps with this
|
||||
process.
|
||||
|
||||
Thank you again for contributing! We will try to test and integrate the change
|
||||
as soon as we can, but be aware we have many GitHub repositories to manage and
|
||||
can't immediately respond to every request. There is no need to bump or check in
|
||||
on a pull request (it will clutter the discussion of the request).
|
||||
|
||||
Also don't be worried if the request is closed or not integrated--sometimes the
|
||||
priorities of Adafruit's GitHub code (education, ease of use) might not match the
|
||||
priorities of the pull request. Don't fret, the open source community thrives on
|
||||
forks and GitHub makes it easy to keep your changes in a forked repo.
|
||||
|
||||
After reviewing the guidelines above you can delete this text from the pull request.
|
@ -0,0 +1,283 @@
|
||||
/***************************************************
|
||||
This is a library for the MCP23017 i2c port expander
|
||||
|
||||
These displays use I2C to communicate, 2 pins are required to
|
||||
interface
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, all text above must be included in any redistribution
|
||||
****************************************************/
|
||||
|
||||
#ifdef __AVR
|
||||
#include <avr/pgmspace.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <pgmspace.h>
|
||||
#endif
|
||||
#include "Adafruit_MCP23017.h"
|
||||
|
||||
#if ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
|
||||
// minihelper to keep Arduino backward compatibility
|
||||
static inline void wiresend(uint8_t x) {
|
||||
#if ARDUINO >= 100
|
||||
Wire.write((uint8_t) x);
|
||||
#else
|
||||
Wire.send(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint8_t wirerecv(void) {
|
||||
#if ARDUINO >= 100
|
||||
return Wire.read();
|
||||
#else
|
||||
return Wire.receive();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Bit number associated to a give Pin
|
||||
*/
|
||||
uint8_t Adafruit_MCP23017::bitForPin(uint8_t pin){
|
||||
return pin%8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register address, port dependent, for a given PIN
|
||||
*/
|
||||
uint8_t Adafruit_MCP23017::regForPin(uint8_t pin, uint8_t portAaddr, uint8_t portBaddr){
|
||||
return(pin<8) ?portAaddr:portBaddr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a given register
|
||||
*/
|
||||
uint8_t Adafruit_MCP23017::readRegister(uint8_t addr){
|
||||
// read the current GPINTEN
|
||||
Wire.beginTransmission(MCP23017_ADDRESS | i2caddr);
|
||||
wiresend(addr);
|
||||
Wire.endTransmission();
|
||||
Wire.requestFrom(MCP23017_ADDRESS | i2caddr, 1);
|
||||
return wirerecv();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Writes a given register
|
||||
*/
|
||||
void Adafruit_MCP23017::writeRegister(uint8_t regAddr, uint8_t regValue){
|
||||
// Write the register
|
||||
Wire.beginTransmission(MCP23017_ADDRESS | i2caddr);
|
||||
wiresend(regAddr);
|
||||
wiresend(regValue);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper to update a single bit of an A/B register.
|
||||
* - Reads the current register value
|
||||
* - Writes the new register value
|
||||
*/
|
||||
void Adafruit_MCP23017::updateRegisterBit(uint8_t pin, uint8_t pValue, uint8_t portAaddr, uint8_t portBaddr) {
|
||||
uint8_t regValue;
|
||||
uint8_t regAddr=regForPin(pin,portAaddr,portBaddr);
|
||||
uint8_t bit=bitForPin(pin);
|
||||
regValue = readRegister(regAddr);
|
||||
|
||||
// set the value for the particular bit
|
||||
bitWrite(regValue,bit,pValue);
|
||||
|
||||
writeRegister(regAddr,regValue);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Initializes the MCP23017 given its HW selected address, see datasheet for Address selection.
|
||||
*/
|
||||
void Adafruit_MCP23017::begin(uint8_t addr) {
|
||||
if (addr > 7) {
|
||||
addr = 7;
|
||||
}
|
||||
i2caddr = addr;
|
||||
|
||||
Wire.begin();
|
||||
|
||||
// set defaults!
|
||||
// all inputs on port A and B
|
||||
writeRegister(MCP23017_IODIRA,0xff);
|
||||
writeRegister(MCP23017_IODIRB,0xff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the default MCP23017, with 000 for the configurable part of the address
|
||||
*/
|
||||
void Adafruit_MCP23017::begin(void) {
|
||||
begin(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the pin mode to either INPUT or OUTPUT
|
||||
*/
|
||||
void Adafruit_MCP23017::pinMode(uint8_t p, uint8_t d) {
|
||||
updateRegisterBit(p,(d==INPUT),MCP23017_IODIRA,MCP23017_IODIRB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads all 16 pins (port A and B) into a single 16 bits variable.
|
||||
*/
|
||||
uint16_t Adafruit_MCP23017::readGPIOAB() {
|
||||
uint16_t ba = 0;
|
||||
uint8_t a;
|
||||
|
||||
// read the current GPIO output latches
|
||||
Wire.beginTransmission(MCP23017_ADDRESS | i2caddr);
|
||||
wiresend(MCP23017_GPIOA);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(MCP23017_ADDRESS | i2caddr, 2);
|
||||
a = wirerecv();
|
||||
ba = wirerecv();
|
||||
ba <<= 8;
|
||||
ba |= a;
|
||||
|
||||
return ba;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a single port, A or B, and return its current 8 bit value.
|
||||
* Parameter b should be 0 for GPIOA, and 1 for GPIOB.
|
||||
*/
|
||||
uint8_t Adafruit_MCP23017::readGPIO(uint8_t b) {
|
||||
|
||||
// read the current GPIO output latches
|
||||
Wire.beginTransmission(MCP23017_ADDRESS | i2caddr);
|
||||
if (b == 0)
|
||||
wiresend(MCP23017_GPIOA);
|
||||
else {
|
||||
wiresend(MCP23017_GPIOB);
|
||||
}
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(MCP23017_ADDRESS | i2caddr, 1);
|
||||
return wirerecv();
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes all the pins in one go. This method is very useful if you are implementing a multiplexed matrix and want to get a decent refresh rate.
|
||||
*/
|
||||
void Adafruit_MCP23017::writeGPIOAB(uint16_t ba) {
|
||||
Wire.beginTransmission(MCP23017_ADDRESS | i2caddr);
|
||||
wiresend(MCP23017_GPIOA);
|
||||
wiresend(ba & 0xFF);
|
||||
wiresend(ba >> 8);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
void Adafruit_MCP23017::digitalWrite(uint8_t pin, uint8_t d) {
|
||||
uint8_t gpio;
|
||||
uint8_t bit=bitForPin(pin);
|
||||
|
||||
|
||||
// read the current GPIO output latches
|
||||
uint8_t regAddr=regForPin(pin,MCP23017_OLATA,MCP23017_OLATB);
|
||||
gpio = readRegister(regAddr);
|
||||
|
||||
// set the pin and direction
|
||||
bitWrite(gpio,bit,d);
|
||||
|
||||
// write the new GPIO
|
||||
regAddr=regForPin(pin,MCP23017_GPIOA,MCP23017_GPIOB);
|
||||
writeRegister(regAddr,gpio);
|
||||
}
|
||||
|
||||
void Adafruit_MCP23017::pullUp(uint8_t p, uint8_t d) {
|
||||
updateRegisterBit(p,d,MCP23017_GPPUA,MCP23017_GPPUB);
|
||||
}
|
||||
|
||||
uint8_t Adafruit_MCP23017::digitalRead(uint8_t pin) {
|
||||
uint8_t bit=bitForPin(pin);
|
||||
uint8_t regAddr=regForPin(pin,MCP23017_GPIOA,MCP23017_GPIOB);
|
||||
return (readRegister(regAddr) >> bit) & 0x1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the interrupt system. both port A and B are assigned the same configuration.
|
||||
* Mirroring will OR both INTA and INTB pins.
|
||||
* Opendrain will set the INT pin to value or open drain.
|
||||
* polarity will set LOW or HIGH on interrupt.
|
||||
* Default values after Power On Reset are: (false, false, LOW)
|
||||
* If you are connecting the INTA/B pin to arduino 2/3, you should configure the interupt handling as FALLING with
|
||||
* the default configuration.
|
||||
*/
|
||||
void Adafruit_MCP23017::setupInterrupts(uint8_t mirroring, uint8_t openDrain, uint8_t polarity){
|
||||
// configure the port A
|
||||
uint8_t ioconfValue=readRegister(MCP23017_IOCONA);
|
||||
bitWrite(ioconfValue,6,mirroring);
|
||||
bitWrite(ioconfValue,2,openDrain);
|
||||
bitWrite(ioconfValue,1,polarity);
|
||||
writeRegister(MCP23017_IOCONA,ioconfValue);
|
||||
|
||||
// Configure the port B
|
||||
ioconfValue=readRegister(MCP23017_IOCONB);
|
||||
bitWrite(ioconfValue,6,mirroring);
|
||||
bitWrite(ioconfValue,2,openDrain);
|
||||
bitWrite(ioconfValue,1,polarity);
|
||||
writeRegister(MCP23017_IOCONB,ioconfValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set's up a pin for interrupt. uses arduino MODEs: CHANGE, FALLING, RISING.
|
||||
*
|
||||
* Note that the interrupt condition finishes when you read the information about the port / value
|
||||
* that caused the interrupt or you read the port itself. Check the datasheet can be confusing.
|
||||
*
|
||||
*/
|
||||
void Adafruit_MCP23017::setupInterruptPin(uint8_t pin, uint8_t mode) {
|
||||
|
||||
// set the pin interrupt control (0 means change, 1 means compare against given value);
|
||||
updateRegisterBit(pin,(mode!=CHANGE),MCP23017_INTCONA,MCP23017_INTCONB);
|
||||
// if the mode is not CHANGE, we need to set up a default value, different value triggers interrupt
|
||||
|
||||
// In a RISING interrupt the default value is 0, interrupt is triggered when the pin goes to 1.
|
||||
// In a FALLING interrupt the default value is 1, interrupt is triggered when pin goes to 0.
|
||||
updateRegisterBit(pin,(mode==FALLING),MCP23017_DEFVALA,MCP23017_DEFVALB);
|
||||
|
||||
// enable the pin for interrupt
|
||||
updateRegisterBit(pin,HIGH,MCP23017_GPINTENA,MCP23017_GPINTENB);
|
||||
|
||||
}
|
||||
|
||||
uint8_t Adafruit_MCP23017::getLastInterruptPin(){
|
||||
uint8_t intf;
|
||||
|
||||
// try port A
|
||||
intf=readRegister(MCP23017_INTFA);
|
||||
for(int i=0;i<8;i++) if (bitRead(intf,i)) return i;
|
||||
|
||||
// try port B
|
||||
intf=readRegister(MCP23017_INTFB);
|
||||
for(int i=0;i<8;i++) if (bitRead(intf,i)) return i+8;
|
||||
|
||||
return MCP23017_INT_ERR;
|
||||
|
||||
}
|
||||
uint8_t Adafruit_MCP23017::getLastInterruptPinValue(){
|
||||
uint8_t intPin=getLastInterruptPin();
|
||||
if(intPin!=MCP23017_INT_ERR){
|
||||
uint8_t intcapreg=regForPin(intPin,MCP23017_INTCAPA,MCP23017_INTCAPB);
|
||||
uint8_t bit=bitForPin(intPin);
|
||||
return (readRegister(intcapreg)>>bit) & (0x01);
|
||||
}
|
||||
|
||||
return MCP23017_INT_ERR;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,97 @@
|
||||
/***************************************************
|
||||
This is a library for the MCP23017 i2c port expander
|
||||
|
||||
These displays use I2C to communicate, 2 pins are required to
|
||||
interface
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, all text above must be included in any redistribution
|
||||
****************************************************/
|
||||
|
||||
#ifndef _Adafruit_MCP23017_H_
|
||||
#define _Adafruit_MCP23017_H_
|
||||
|
||||
// Don't forget the Wire library
|
||||
#ifndef ARDUINO_AVR_GEMMA
|
||||
//TinyWireM is now part of
|
||||
// Adafruit version of Wire Library, so this
|
||||
// will work with Adafruit ATtiny85's
|
||||
//But Arduino Gemma doesn't use that library
|
||||
// We do NOT want to include Wire if it's an arduino Gemma
|
||||
#include <Wire.h>
|
||||
#else
|
||||
#include <TinyWireM.h>
|
||||
#define Wire TinyWireM
|
||||
#endif
|
||||
|
||||
|
||||
class Adafruit_MCP23017 {
|
||||
public:
|
||||
void begin(uint8_t addr);
|
||||
void begin(void);
|
||||
|
||||
void pinMode(uint8_t p, uint8_t d);
|
||||
void digitalWrite(uint8_t p, uint8_t d);
|
||||
void pullUp(uint8_t p, uint8_t d);
|
||||
uint8_t digitalRead(uint8_t p);
|
||||
|
||||
void writeGPIOAB(uint16_t);
|
||||
uint16_t readGPIOAB();
|
||||
uint8_t readGPIO(uint8_t b);
|
||||
|
||||
void setupInterrupts(uint8_t mirroring, uint8_t open, uint8_t polarity);
|
||||
void setupInterruptPin(uint8_t p, uint8_t mode);
|
||||
uint8_t getLastInterruptPin();
|
||||
uint8_t getLastInterruptPinValue();
|
||||
|
||||
private:
|
||||
uint8_t i2caddr;
|
||||
|
||||
uint8_t bitForPin(uint8_t pin);
|
||||
uint8_t regForPin(uint8_t pin, uint8_t portAaddr, uint8_t portBaddr);
|
||||
|
||||
uint8_t readRegister(uint8_t addr);
|
||||
void writeRegister(uint8_t addr, uint8_t value);
|
||||
|
||||
/**
|
||||
* Utility private method to update a register associated with a pin (whether port A/B)
|
||||
* reads its value, updates the particular bit, and writes its value.
|
||||
*/
|
||||
void updateRegisterBit(uint8_t p, uint8_t pValue, uint8_t portAaddr, uint8_t portBaddr);
|
||||
|
||||
};
|
||||
|
||||
#define MCP23017_ADDRESS 0x20
|
||||
|
||||
// registers
|
||||
#define MCP23017_IODIRA 0x00
|
||||
#define MCP23017_IPOLA 0x02
|
||||
#define MCP23017_GPINTENA 0x04
|
||||
#define MCP23017_DEFVALA 0x06
|
||||
#define MCP23017_INTCONA 0x08
|
||||
#define MCP23017_IOCONA 0x0A
|
||||
#define MCP23017_GPPUA 0x0C
|
||||
#define MCP23017_INTFA 0x0E
|
||||
#define MCP23017_INTCAPA 0x10
|
||||
#define MCP23017_GPIOA 0x12
|
||||
#define MCP23017_OLATA 0x14
|
||||
|
||||
|
||||
#define MCP23017_IODIRB 0x01
|
||||
#define MCP23017_IPOLB 0x03
|
||||
#define MCP23017_GPINTENB 0x05
|
||||
#define MCP23017_DEFVALB 0x07
|
||||
#define MCP23017_INTCONB 0x09
|
||||
#define MCP23017_IOCONB 0x0B
|
||||
#define MCP23017_GPPUB 0x0D
|
||||
#define MCP23017_INTFB 0x0F
|
||||
#define MCP23017_INTCAPB 0x11
|
||||
#define MCP23017_GPIOB 0x13
|
||||
#define MCP23017_OLATB 0x15
|
||||
|
||||
#define MCP23017_INT_ERR 255
|
||||
|
||||
#endif
|
@ -0,0 +1,15 @@
|
||||
This is a library for the MCP23017 I2c Port Expander
|
||||
|
||||
These chips use I2C to communicate, 2 pins required to interface
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, check license.txt for more information
|
||||
All text above must be included in any redistribution
|
||||
|
||||
To download. click the DOWNLOADS button in the top right corner, rename the uncompressed folder Adafruit_MCP23017. Check that the Adafruit_MCP23017 folder contains Adafruit_MCP23017.cpp and Adafruit_MCP23017.h
|
||||
|
||||
Place the Adafruit_MCP23017 library folder your <arduinosketchfolder>/libraries/ folder. You may need to create the libraries subfolder if its your first library. Restart the IDE.
|
@ -0,0 +1,32 @@
|
||||
#include <Wire.h>
|
||||
#include "Adafruit_MCP23017.h"
|
||||
|
||||
// Basic pin reading and pullup test for the MCP23017 I/O expander
|
||||
// public domain!
|
||||
|
||||
// Connect pin #12 of the expander to Analog 5 (i2c clock)
|
||||
// Connect pin #13 of the expander to Analog 4 (i2c data)
|
||||
// Connect pins #15, 16 and 17 of the expander to ground (address selection)
|
||||
// Connect pin #9 of the expander to 5V (power)
|
||||
// Connect pin #10 of the expander to ground (common ground)
|
||||
// Connect pin #18 through a ~10kohm resistor to 5V (reset pin, active low)
|
||||
|
||||
// Input #0 is on pin 21 so connect a button or switch from there to ground
|
||||
|
||||
Adafruit_MCP23017 mcp;
|
||||
|
||||
void setup() {
|
||||
mcp.begin(); // use default address 0
|
||||
|
||||
mcp.pinMode(0, INPUT);
|
||||
mcp.pullUp(0, HIGH); // turn on a 100K pullup internally
|
||||
|
||||
pinMode(13, OUTPUT); // use the p13 LED as debugging
|
||||
}
|
||||
|
||||
|
||||
|
||||
void loop() {
|
||||
// The LED will 'echo' the button
|
||||
digitalWrite(13, mcp.digitalRead(0));
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
// Install the LowPower library for optional sleeping support.
|
||||
// See loop() function comments for details on usage.
|
||||
//#include <LowPower.h>
|
||||
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_MCP23017.h>
|
||||
|
||||
Adafruit_MCP23017 mcp;
|
||||
|
||||
byte ledPin=13;
|
||||
|
||||
// Interrupts from the MCP will be handled by this PIN
|
||||
byte arduinoIntPin=3;
|
||||
|
||||
// ... and this interrupt vector
|
||||
byte arduinoInterrupt=1;
|
||||
|
||||
volatile boolean awakenByInterrupt = false;
|
||||
|
||||
// Two pins at the MCP (Ports A/B where some buttons have been setup.)
|
||||
// Buttons connect the pin to grond, and pins are pulled up.
|
||||
byte mcpPinA=7;
|
||||
byte mcpPinB=15;
|
||||
|
||||
void setup(){
|
||||
|
||||
Serial.begin(9600);
|
||||
Serial.println("MCP23007 Interrupt Test");
|
||||
|
||||
pinMode(arduinoIntPin,INPUT);
|
||||
|
||||
mcp.begin(); // use default address 0
|
||||
|
||||
// We mirror INTA and INTB, so that only one line is required between MCP and Arduino for int reporting
|
||||
// The INTA/B will not be Floating
|
||||
// INTs will be signaled with a LOW
|
||||
mcp.setupInterrupts(true,false,LOW);
|
||||
|
||||
// configuration for a button on port A
|
||||
// interrupt will triger when the pin is taken to ground by a pushbutton
|
||||
mcp.pinMode(mcpPinA, INPUT);
|
||||
mcp.pullUp(mcpPinA, HIGH); // turn on a 100K pullup internally
|
||||
mcp.setupInterruptPin(mcpPinA,FALLING);
|
||||
|
||||
// similar, but on port B.
|
||||
mcp.pinMode(mcpPinB, INPUT);
|
||||
mcp.pullUp(mcpPinB, HIGH); // turn on a 100K pullup internall
|
||||
mcp.setupInterruptPin(mcpPinB,FALLING);
|
||||
|
||||
// We will setup a pin for flashing from the int routine
|
||||
pinMode(ledPin, OUTPUT); // use the p13 LED as debugging
|
||||
|
||||
}
|
||||
|
||||
// The int handler will just signal that the int has happen
|
||||
// we will do the work from the main loop.
|
||||
void intCallBack(){
|
||||
awakenByInterrupt=true;
|
||||
}
|
||||
|
||||
void handleInterrupt(){
|
||||
|
||||
// Get more information from the MCP from the INT
|
||||
uint8_t pin=mcp.getLastInterruptPin();
|
||||
uint8_t val=mcp.getLastInterruptPinValue();
|
||||
|
||||
// We will flash the led 1 or 2 times depending on the PIN that triggered the Interrupt
|
||||
// 3 and 4 flases are supposed to be impossible conditions... just for debugging.
|
||||
uint8_t flashes=4;
|
||||
if(pin==mcpPinA) flashes=1;
|
||||
if(pin==mcpPinB) flashes=2;
|
||||
if(val!=LOW) flashes=3;
|
||||
|
||||
// simulate some output associated to this
|
||||
for(int i=0;i<flashes;i++){
|
||||
delay(100);
|
||||
digitalWrite(ledPin,HIGH);
|
||||
delay(100);
|
||||
digitalWrite(ledPin,LOW);
|
||||
}
|
||||
|
||||
// we have to wait for the interrupt condition to finish
|
||||
// otherwise we might go to sleep with an ongoing condition and never wake up again.
|
||||
// as, an action is required to clear the INT flag, and allow it to trigger again.
|
||||
// see datasheet for datails.
|
||||
while( ! (mcp.digitalRead(mcpPinB) && mcp.digitalRead(mcpPinA) ));
|
||||
// and clean queued INT signal
|
||||
cleanInterrupts();
|
||||
}
|
||||
|
||||
// handy for interrupts triggered by buttons
|
||||
// normally signal a few due to bouncing issues
|
||||
void cleanInterrupts(){
|
||||
EIFR=0x01;
|
||||
awakenByInterrupt=false;
|
||||
}
|
||||
|
||||
/**
|
||||
* main routine: sleep the arduino, and wake up on Interrups.
|
||||
* the LowPower library, or similar is required for sleeping, but sleep is simulated here.
|
||||
* It is actually posible to get the MCP to draw only 1uA while in standby as the datasheet claims,
|
||||
* however there is no stadndby mode. Its all down to seting up each pin in a way that current does not flow.
|
||||
* and you can wait for interrupts while waiting.
|
||||
*/
|
||||
void loop(){
|
||||
|
||||
// enable interrupts before going to sleep/wait
|
||||
// And we setup a callback for the arduino INT handler.
|
||||
attachInterrupt(arduinoInterrupt,intCallBack,FALLING);
|
||||
|
||||
// Simulate a deep sleep
|
||||
while(!awakenByInterrupt);
|
||||
// Or sleep the arduino, this lib is great, if you have it.
|
||||
//LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF);
|
||||
|
||||
// disable interrupts while handling them.
|
||||
detachInterrupt(arduinoInterrupt);
|
||||
|
||||
if(awakenByInterrupt) handleInterrupt();
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,35 @@
|
||||
#include <Wire.h>
|
||||
#include "Adafruit_MCP23017.h"
|
||||
|
||||
// Basic pin reading and pullup test for the MCP23017 I/O expander
|
||||
// public domain!
|
||||
|
||||
// Connect pin #12 of the expander to Analog 5 (i2c clock)
|
||||
// Connect pin #13 of the expander to Analog 4 (i2c data)
|
||||
// Connect pins #15, 16 and 17 of the expander to ground (address selection)
|
||||
// Connect pin #9 of the expander to 5V (power)
|
||||
// Connect pin #10 of the expander to ground (common ground)
|
||||
// Connect pin #18 through a ~10kohm resistor to 5V (reset pin, active low)
|
||||
|
||||
// Output #0 is on pin 21 so connect an LED or whatever from that to ground
|
||||
|
||||
Adafruit_MCP23017 mcp;
|
||||
|
||||
void setup() {
|
||||
mcp.begin(); // use default address 0
|
||||
|
||||
mcp.pinMode(0, OUTPUT);
|
||||
}
|
||||
|
||||
|
||||
// flip the pin #0 up and down
|
||||
|
||||
void loop() {
|
||||
delay(100);
|
||||
|
||||
mcp.digitalWrite(0, HIGH);
|
||||
|
||||
delay(100);
|
||||
|
||||
mcp.digitalWrite(0, LOW);
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map for MCP23017
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
MCP23017 KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
pullUp KEYWORD2
|
||||
writeGPIOAB KEYWORD2
|
||||
readGPIOAB KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
@ -0,0 +1,9 @@
|
||||
name=Adafruit MCP23017 Arduino Library
|
||||
version=1.0.3
|
||||
author=Adafruit
|
||||
maintainer=Adafruit <info@adafruit.com>
|
||||
sentence=Library for the MCP23017 I2C Port Expander
|
||||
paragraph=Library for the MCP23017 I2C Port Expander
|
||||
category=Signal Input/Output
|
||||
url=https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library
|
||||
architectures=*
|
@ -0,0 +1,26 @@
|
||||
Software License Agreement (BSD License)
|
||||
|
||||
Copyright (c) 2012, Adafruit Industries
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holders nor the
|
||||
names of its 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 ''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 HOLDER 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.
|
BIN
firmware/lib/CheapStepper-master.zip
Normal file
BIN
firmware/lib/CheapStepper-master.zip
Normal file
Binary file not shown.
297
firmware/lib/CheapStepper-master/CheapStepper.cpp
Normal file
297
firmware/lib/CheapStepper-master/CheapStepper.cpp
Normal file
@ -0,0 +1,297 @@
|
||||
/* CheapStepper.cpp -
|
||||
v0.2
|
||||
Library for the 28BYJ-48 stepper motor, using ULN2003 driver board
|
||||
https://arduino-info.wikispaces.com/SmallSteppers
|
||||
|
||||
Library written by Tyler Henry, 6/2016
|
||||
|
||||
uses 8-step sequence: A-AB-B-BC-C-CD-D-DA
|
||||
|
||||
motor has gear ratio of either:
|
||||
64:1 (per manufacturer specs)
|
||||
or
|
||||
63.68395:1 measured
|
||||
(see: http://forum.arduino.cc/index.php?topic=71964.15)
|
||||
* 64 steps per internal motor rev
|
||||
=
|
||||
|
||||
4096 total mini-steps / revolution
|
||||
or ~4076 (4075.7728) depending on exact gear ratio
|
||||
|
||||
assumes 5v power source for rpm calc
|
||||
*/
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "CheapStepper.h"
|
||||
|
||||
|
||||
CheapStepper::CheapStepper () {
|
||||
for (int pin=0; pin<4; pin++){
|
||||
pinMode(pins[pin], OUTPUT);
|
||||
}
|
||||
}
|
||||
|
||||
CheapStepper::CheapStepper (int in1, int in2, int in3, int in4) {
|
||||
|
||||
pins[0] = in1;
|
||||
pins[1] = in2;
|
||||
pins[2] = in3;
|
||||
pins[3] = in4;
|
||||
CheapStepper();
|
||||
}
|
||||
|
||||
void CheapStepper::setRpm (int rpm){
|
||||
|
||||
delay = calcDelay(rpm);
|
||||
}
|
||||
|
||||
void CheapStepper::move (bool clockwise, int numSteps){
|
||||
|
||||
for (int n=0; n<numSteps; n++){
|
||||
step(clockwise);
|
||||
}
|
||||
}
|
||||
|
||||
void CheapStepper::moveTo (bool clockwise, int toStep){
|
||||
|
||||
// keep to 0-(totalSteps-1) range
|
||||
if (toStep >= totalSteps) toStep %= totalSteps;
|
||||
else if (toStep < 0) {
|
||||
toStep %= totalSteps; // returns negative if toStep not multiple of totalSteps
|
||||
if (toStep < 0) toStep += totalSteps; // shift into 0-(totalSteps-1) range
|
||||
}
|
||||
while (stepN != toStep){
|
||||
step(clockwise);
|
||||
}
|
||||
}
|
||||
|
||||
void CheapStepper::moveDegrees (bool clockwise, int deg){
|
||||
|
||||
int nSteps = (unsigned long) deg * totalSteps / 360;
|
||||
move(clockwise, nSteps);
|
||||
}
|
||||
|
||||
void CheapStepper::moveToDegree (bool clockwise, int deg){
|
||||
|
||||
// keep to 0-359 range
|
||||
if (deg >= 360) deg %= 360;
|
||||
else if (deg < 0) {
|
||||
deg %= 360; // returns negative if deg not multiple of 360
|
||||
if (deg < 0) deg += 360; // shift into 0-359 range
|
||||
}
|
||||
|
||||
int toStep = deg * totalSteps / 360;
|
||||
moveTo (clockwise, toStep);
|
||||
}
|
||||
|
||||
|
||||
// NON-BLOCKING MOVES
|
||||
|
||||
void CheapStepper::newMove (bool clockwise, int numSteps){
|
||||
|
||||
// numSteps sign ignored
|
||||
// stepsLeft signed positive if clockwise, neg if ccw
|
||||
|
||||
if (clockwise) stepsLeft = abs(numSteps);
|
||||
else stepsLeft = -1 * abs(numSteps);
|
||||
|
||||
lastStepTime = micros();
|
||||
}
|
||||
|
||||
void CheapStepper::newMoveTo (bool clockwise, int toStep){
|
||||
|
||||
// keep toStep in 0-(totalSteps-1) range
|
||||
if (toStep >= totalSteps) toStep %= totalSteps;
|
||||
else if (toStep < 0) {
|
||||
toStep %= totalSteps; // returns negative if toStep not multiple of totalSteps
|
||||
if (toStep < 0) toStep += totalSteps; // shift into 0-(totalSteps-1) range
|
||||
}
|
||||
|
||||
if (clockwise) stepsLeft = abs(toStep - stepN);
|
||||
// clockwise: simple diff, always pos
|
||||
else stepsLeft = -1*(totalSteps - abs(toStep - stepN));
|
||||
// counter-clockwise: totalSteps - diff, made neg
|
||||
|
||||
lastStepTime = micros();
|
||||
}
|
||||
|
||||
void CheapStepper::newMoveDegrees (bool clockwise, int deg){
|
||||
|
||||
int nSteps = (unsigned long) deg * totalSteps / 360;
|
||||
newMove (clockwise, nSteps);
|
||||
}
|
||||
|
||||
void CheapStepper::newMoveToDegree (bool clockwise, int deg){
|
||||
|
||||
// keep to 0-359 range
|
||||
if (deg >= 360) deg %= 360;
|
||||
else if (deg < 0) {
|
||||
deg %= 360; // returns negative if deg not multiple of 360
|
||||
if (deg < 0) deg += 360; // shift into 0-359 range
|
||||
}
|
||||
|
||||
int toStep = deg * totalSteps / 360;
|
||||
newMoveTo (clockwise, toStep);
|
||||
}
|
||||
|
||||
void CheapStepper::run(){
|
||||
|
||||
if (micros() - lastStepTime >= delay) { // if time for step
|
||||
if (stepsLeft > 0) { // clockwise
|
||||
stepCW();
|
||||
stepsLeft--;
|
||||
} else if (stepsLeft < 0){ // counter-clockwise
|
||||
stepCCW();
|
||||
stepsLeft++;
|
||||
}
|
||||
|
||||
lastStepTime = micros();
|
||||
}
|
||||
}
|
||||
|
||||
void CheapStepper::stop(){
|
||||
|
||||
stepsLeft = 0;
|
||||
}
|
||||
|
||||
|
||||
void CheapStepper::step(bool clockwise){
|
||||
|
||||
if (clockwise) seqCW();
|
||||
else seqCCW();
|
||||
}
|
||||
|
||||
|
||||
/////////////
|
||||
// PRIVATE //
|
||||
/////////////
|
||||
|
||||
int CheapStepper::calcDelay (int rpm){
|
||||
|
||||
if (rpm < 6) return delay; // will overheat, no change
|
||||
else if (rpm >= 24) return 600; // highest speed
|
||||
|
||||
unsigned long d = 60000000 / (totalSteps* (unsigned long) rpm);
|
||||
// in range: 600-1465 microseconds (24-1 rpm)
|
||||
return (int) d;
|
||||
|
||||
}
|
||||
|
||||
int CheapStepper::calcRpm (int _delay){
|
||||
|
||||
unsigned long rpm = 60000000 / (unsigned long) _delay / totalSteps;
|
||||
return (int) rpm;
|
||||
|
||||
}
|
||||
|
||||
void CheapStepper::seqCW (){
|
||||
seqN++;
|
||||
if (seqN > 7) seqN = 0; // roll over to A seq
|
||||
seq(seqN);
|
||||
|
||||
stepN++; // track miniSteps
|
||||
if (stepN >= totalSteps){
|
||||
stepN -=totalSteps; // keep stepN within 0-(totalSteps-1)
|
||||
}
|
||||
}
|
||||
|
||||
void CheapStepper::seqCCW (){
|
||||
seqN--;
|
||||
if (seqN < 0) seqN = 7; // roll over to DA seq
|
||||
seq(seqN);
|
||||
|
||||
stepN--; // track miniSteps
|
||||
if (stepN < 0){
|
||||
stepN +=totalSteps; // keep stepN within 0-(totalSteps-1)
|
||||
}
|
||||
}
|
||||
|
||||
void CheapStepper::seq (int seqNum){
|
||||
|
||||
int pattern[4];
|
||||
// A,B,C,D HIGH/LOW pattern to write to driver board
|
||||
|
||||
switch(seqNum){
|
||||
case 0:
|
||||
{
|
||||
pattern[0] = 1;
|
||||
pattern[1] = 0;
|
||||
pattern[2] = 0;
|
||||
pattern[3] = 0;
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
pattern[0] = 1;
|
||||
pattern[1] = 1;
|
||||
pattern[2] = 0;
|
||||
pattern[3] = 0;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
pattern[0] = 0;
|
||||
pattern[1] = 1;
|
||||
pattern[2] = 0;
|
||||
pattern[3] = 0;
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
pattern[0] = 0;
|
||||
pattern[1] = 1;
|
||||
pattern[2] = 1;
|
||||
pattern[3] = 0;
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
pattern[0] = 0;
|
||||
pattern[1] = 0;
|
||||
pattern[2] = 1;
|
||||
pattern[3] = 0;
|
||||
break;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
pattern[0] = 0;
|
||||
pattern[1] = 0;
|
||||
pattern[2] = 1;
|
||||
pattern[3] = 1;
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
pattern[0] = 0;
|
||||
pattern[1] = 0;
|
||||
pattern[2] = 0;
|
||||
pattern[3] = 1;
|
||||
break;
|
||||
}
|
||||
case 7:
|
||||
{
|
||||
pattern[0] = 1;
|
||||
pattern[1] = 0;
|
||||
pattern[2] = 0;
|
||||
pattern[3] = 1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
pattern[0] = 0;
|
||||
pattern[1] = 0;
|
||||
pattern[2] = 0;
|
||||
pattern[3] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// write pattern to pins
|
||||
for (int p=0; p<4; p++){
|
||||
digitalWrite(pins[p], pattern[p]);
|
||||
}
|
||||
delayMicroseconds(delay);
|
||||
}
|
||||
|
||||
|
128
firmware/lib/CheapStepper-master/CheapStepper.h
Normal file
128
firmware/lib/CheapStepper-master/CheapStepper.h
Normal file
@ -0,0 +1,128 @@
|
||||
/* CheapStepper.h -
|
||||
v0.2
|
||||
Library for the 28BYJ-48 stepper motor, using ULN2003 driver board
|
||||
https://arduino-info.wikispaces.com/SmallSteppers
|
||||
|
||||
Library written by Tyler Henry, 6/2016
|
||||
|
||||
uses 8-step sequence: A-AB-B-BC-C-CD-D-DA
|
||||
|
||||
motor has gear ratio of either:
|
||||
64:1 (per manufacturer specs)
|
||||
or
|
||||
63.68395:1 measured
|
||||
(see: http://forum.arduino.cc/index.php?topic=71964.15)
|
||||
* 64 steps per internal motor rev
|
||||
=
|
||||
|
||||
4096 total mini-steps / revolution
|
||||
or ~4076 (4075.7728) depending on exact gear ratio
|
||||
|
||||
assumes 5v power source for rpm calc
|
||||
*/
|
||||
|
||||
#ifndef CHEAPSTEPPER_H
|
||||
#define CHEAPSTEPPER_H
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
class CheapStepper
|
||||
{
|
||||
|
||||
public:
|
||||
CheapStepper();
|
||||
CheapStepper (int in1, int in2, int in3, int in4);
|
||||
|
||||
void setRpm (int rpm); // sets speed (10-24 rpm, hi-low torque)
|
||||
// <6 rpm blocked in code, may overheat
|
||||
// 23-24rpm may skip
|
||||
|
||||
void set4076StepMode() { totalSteps = 4076; }
|
||||
void setTotalSteps (int numSteps) { totalSteps = numSteps; }
|
||||
// allows custom # of steps (usually 4076)
|
||||
|
||||
// blocking! (pauses arduino until move is done)
|
||||
void move (bool clockwise, int numSteps); // 4096 steps = 1 revolution
|
||||
void moveTo (bool clockwise, int toStep); // move to specific step position
|
||||
void moveDegrees (bool clockwise, int deg);
|
||||
void moveToDegree (bool clockwise, int deg);
|
||||
|
||||
void moveCW (int numSteps) { move (true, numSteps); }
|
||||
void moveCCW (int numSteps) { move (false, numSteps); }
|
||||
void moveToCW (int toStep) { moveTo (true, toStep); }
|
||||
void moveToCCW (int toStep) { moveTo (false, toStep); }
|
||||
void moveDegreesCW (int deg) { moveDegrees (true, deg); }
|
||||
void moveDegreesCCW (int deg) { moveDegrees (false, deg); }
|
||||
void moveToDegreeCW (int deg) { moveToDegree (true, deg); }
|
||||
void moveToDegreeCCW (int deg) { moveToDegree (false, deg); }
|
||||
|
||||
|
||||
// non-blocking versions of move()
|
||||
// call run() in loop to keep moving
|
||||
|
||||
void newMove (bool clockwise, int numSteps);
|
||||
void newMoveTo (bool clockwise, int toStep);
|
||||
void newMoveDegrees (bool clockwise, int deg);
|
||||
void newMoveToDegree (bool clockwise, int deg);
|
||||
|
||||
void run();
|
||||
void stop();
|
||||
|
||||
void newMoveCW(int numSteps) { newMove(true, numSteps); }
|
||||
void newMoveCCW(int numSteps) { newMove(false, numSteps); }
|
||||
void newMoveToCW(int toStep) { newMoveTo(true, toStep); }
|
||||
void newMoveToCCW(int toStep) { newMoveTo(false, toStep); }
|
||||
void newMoveDegreesCW(int deg) { newMoveDegrees(true, deg); }
|
||||
void newMoveDegreesCCW(int deg) { newMoveDegrees(false, deg); }
|
||||
void newMoveToDegreeCW(int deg) { newMoveToDegree(true, deg); }
|
||||
void newMoveToDegreeCCW(int deg) { newMoveToDegree(false, deg); }
|
||||
|
||||
|
||||
|
||||
void step (bool clockwise);
|
||||
// move 1 step clockwise or counter-clockwise
|
||||
|
||||
void stepCW () { step (true); } // move 1 step clockwise
|
||||
void stepCCW () { step (false); } // move 1 step counter-clockwise
|
||||
|
||||
int getStep() { return stepN; } // returns current miniStep position
|
||||
int getDelay() { return delay; } // returns current delay (microseconds)
|
||||
int getRpm() { return calcRpm(); } // returns current rpm
|
||||
int getPin(int p) {
|
||||
if (p<4) return pins[p]; // returns pin #
|
||||
return 0; // default 0
|
||||
}
|
||||
int getStepsLeft() { return stepsLeft; } // returns steps left in current move
|
||||
|
||||
private:
|
||||
|
||||
int calcDelay(int rpm); // calcs microsecond step delay for given rpm
|
||||
int calcRpm(int _delay); // calcs rpm for given delay in microseconds
|
||||
int calcRpm(){
|
||||
return calcRpm(delay); // calcs rpm from current delay
|
||||
}
|
||||
|
||||
void seqCW();
|
||||
void seqCCW();
|
||||
void seq(int seqNum); // send specific sequence num to driver
|
||||
|
||||
int pins[4] = {8,9,10,11}; // in1, in2, in3, in4
|
||||
|
||||
int stepN = 0; // keeps track of step position
|
||||
// 0-4095 (4096 mini-steps / revolution) or maybe 4076...
|
||||
int totalSteps = 4096;
|
||||
|
||||
int delay = 900; // microsecond delay between steps
|
||||
// 900 ~= 16.25 rpm
|
||||
// low speed (high torque) = 1465 ~= 1 rpm
|
||||
// high speed (low torque) = 600 ~= 24 rpm
|
||||
|
||||
int seqN = -1; // keeps track of sequence number
|
||||
|
||||
// variables for non-blocking moves:
|
||||
unsigned long lastStepTime; // time in microseconds that last step happened
|
||||
int stepsLeft = 0; // steps left to move, neg for counter-clockwise
|
||||
|
||||
};
|
||||
|
||||
#endif
|
78
firmware/lib/CheapStepper-master/README.md
Normal file
78
firmware/lib/CheapStepper-master/README.md
Normal file
@ -0,0 +1,78 @@
|
||||
# CheapStepper v0.2 #
|
||||
## An Arduino library for the 28BYJ-48 stepper motor using ULN2003 driver board ##
|
||||
|
||||
#### created by Tyler Henry, 6/2016 ####
|
||||
|
||||
|
||||
You can read some more info on the cheap yet worthy 28BYJ-48 stepper motor [here](https://arduino-info.wikispaces.com/SmallSteppers).
|
||||
|
||||
## Wiring example
|
||||
|
||||
<img src="https://github.com/tyhenry/CheapStepper/blob/master/extras/connections.png?raw=true" width="400">
|
||||
|
||||
## Library Info
|
||||
|
||||
### Half-stepping
|
||||
CheapStepper uses an 8 mini-step sequence to perform all moves
|
||||
([a.k.a half-stepping](https://www.youtube.com/watch?v=B86nqDRskVU&feature=youtu.be&t=11m0s)): A-AB-B-BC-C-CD-D-DA
|
||||
|
||||
### Gear Ratio
|
||||
Depending on whom you ask, the 28BYJ-48 motor has an internal gear ratio of either:
|
||||
|
||||
- 64:1 (per manufacturer specs) or
|
||||
- 63.68395:1 (measured... see this [Arduino Forum topic](http://forum.arduino.cc/index.php?topic=71964.15) for more info)
|
||||
|
||||
### Total Steps
|
||||
|
||||
64:1 gear ratio **\*** 64 steps (1 step = 8 mini-steps) per internal motor revolution =
|
||||
4096 total mini-steps / revolution
|
||||
or ~4076 (4075.7728) if the gear ratio is 63.68395:1
|
||||
|
||||
CheapStepper library defaults to 4096 mini-steps but you can call:
|
||||
`CheapStepper::set4076StepMode()` to use 4076 steps
|
||||
or `CheapStepper::setTotalSteps(int numSteps)` to use a custom amount
|
||||
|
||||
|
||||
### Power
|
||||
CheapStepper assumes a 5v power source for RPM calculations.
|
||||
It's best to use an external power supply like [this](https://www.adafruit.com/products/276), wired directly to the ULN2003 driver board, rather than draw from the Arduino's onboard power, which may have insufficient amperage (>100mA needed).
|
||||
|
||||
----
|
||||
## Blocking Moves
|
||||
_The Arduino sketch "pauses" during move()_
|
||||
|
||||
- move (boolean clockwise, int numSteps);
|
||||
- moveTo (boolean clockwise, int toStep);
|
||||
- moveDegrees (boolean clockwise, int degrees);
|
||||
- moveToDegree (boolean clockwise, int toDegree);
|
||||
|
||||
----
|
||||
## Non-blocking Moves
|
||||
_The Arduino sketch will continue running during the move.
|
||||
You must call run() on your stepper during loop()_
|
||||
|
||||
- newMove (boolean clockwise, int numSteps);
|
||||
- newMoveTo (boolean clockwise, int toStep);
|
||||
- newMoveDegrees (boolean clockwise, int degrees);
|
||||
- newMoveToDegree (boolean clockwise, int toDegree);
|
||||
|
||||
### Note
|
||||
* must call run() during loop to continue move
|
||||
* call stop() to cancel/end move
|
||||
|
||||
----
|
||||
### Move a Single Mini-Step<br/>(1/8 of 8 Step Sequence)
|
||||
|
||||
- step (boolean clockwise);
|
||||
- or stepCW(); or stepCCW();
|
||||
|
||||
----
|
||||
#### All move functions have ...CW() or ...CCW() variants:
|
||||
e.g.
|
||||
|
||||
- move 8 steps clockwise:
|
||||
`move (true, 8);` is the same as
|
||||
`moveCW (8);`
|
||||
- create new move of 90 degrees counter-clockwise
|
||||
`newMoveDegrees (false, 90);` is the same as
|
||||
`newMoveDegreesCCW (90);`
|
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* cheapStepper_move.ino
|
||||
* ///////////////////////////////////////////
|
||||
* using CheapStepper Arduino library v.0.2.0
|
||||
* created by Tyler Henry, 7/2016
|
||||
* ///////////////////////////////////////////
|
||||
*
|
||||
* This sketch illustrates the library's
|
||||
* "blocking" move functions -
|
||||
* i.e. the move will "pause" the arduino sketch
|
||||
* -- for non-blocking moves, see cheapStepper_newMoveTo.ino example
|
||||
*
|
||||
* This sketch also shows how to set the RPM
|
||||
* and shows a few different types of move functions
|
||||
* - by steps or by degrees.
|
||||
*
|
||||
* Blocking moves are useful if you need a specific RPM
|
||||
* but don't need your arduino to perform other functions
|
||||
* while the stepper is moving.
|
||||
*
|
||||
* //////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
// first, include the library :)
|
||||
|
||||
#include <CheapStepper.h>
|
||||
|
||||
// next, declare the stepper
|
||||
// and connect pins 8,9,10,11 to IN1,IN2,IN3,IN4 on ULN2003 board
|
||||
|
||||
CheapStepper stepper (8,9,10,11);
|
||||
|
||||
// let's create a boolean variable to save the direction of our rotation
|
||||
|
||||
boolean moveClockwise = true;
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
// let's set a custom speed of 20rpm (the default is ~16.25rpm)
|
||||
|
||||
stepper.setRpm(20);
|
||||
/* Note: CheapStepper library assumes you are powering your 28BYJ-48 stepper
|
||||
* using an external 5V power supply (>100mA) for RPM calculations
|
||||
* -- don't try to power the stepper directly from the Arduino
|
||||
*
|
||||
* accepted RPM range: 6RPM (may overheat) - 24RPM (may skip)
|
||||
* ideal range: 10RPM (safe, high torque) - 22RPM (fast, low torque)
|
||||
*/
|
||||
|
||||
// now let's set up a serial connection and print some stepper info to the console
|
||||
|
||||
Serial.begin(9600); Serial.println();
|
||||
Serial.print(stepper.getRpm()); // get the RPM of the stepper
|
||||
Serial.print(" rpm = delay of ");
|
||||
Serial.print(stepper.getDelay()); // get delay between steps for set RPM
|
||||
Serial.print(" microseconds between steps");
|
||||
Serial.println();
|
||||
|
||||
// stepper.setTotalSteps(4076);
|
||||
/* you can uncomment the above line if you think your motor
|
||||
* is geared 63.68395:1 (measured) rather than 64:1 (advertised)
|
||||
* which would make the total steps 4076 (rather than default 4096)
|
||||
* for more info see: http://forum.arduino.cc/index.php?topic=71964.15
|
||||
*/
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
// let's do a clockwise move first
|
||||
|
||||
moveClockwise = true;
|
||||
|
||||
// let's move the stepper clockwise to position 2048
|
||||
// which is 180 degrees, a half-turn (if using default of 4096 total steps)
|
||||
|
||||
stepper.moveTo (moveClockwise, 2048);
|
||||
|
||||
// now let's print the stepper position to the console
|
||||
|
||||
Serial.print("step position: ");
|
||||
Serial.print(stepper.getStep()); // get the current step position
|
||||
Serial.print(" / 4096");
|
||||
Serial.println();
|
||||
|
||||
// now let's wait one second
|
||||
|
||||
delay(1000); // wait a sec
|
||||
|
||||
// and now let's move another 90 degrees (a quarter-turn) clockwise
|
||||
|
||||
stepper.moveDegrees (moveClockwise, 90);
|
||||
// stepper.moveDegreesCW (90); <--- another way to do a clockwise 90 degree turn
|
||||
|
||||
// let's print the stepper position to the console again
|
||||
|
||||
Serial.print("step position: ");
|
||||
Serial.print(stepper.getStep());
|
||||
Serial.print(" / 4096");
|
||||
Serial.println();
|
||||
|
||||
// and wait another second
|
||||
|
||||
delay(1000);
|
||||
|
||||
// ok, now let's reverse directions (to counter-clockwise)
|
||||
|
||||
moveClockwise = false;
|
||||
|
||||
// and move back to the start position (0 degree)
|
||||
|
||||
stepper.moveToDegree (moveClockwise, 0);
|
||||
// moveClockwise is now false, so move counter-clockwise back to start
|
||||
|
||||
// let's print the position to the console once again
|
||||
|
||||
Serial.print("step position: ");
|
||||
Serial.print(stepper.getStep());
|
||||
Serial.print(" / 4096");
|
||||
Serial.println();
|
||||
|
||||
// and wait another second before starting loop() over
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
@ -0,0 +1,110 @@
|
||||
|
||||
/*
|
||||
* cheapStepper_newMoveTo.ino
|
||||
* ///////////////////////////////////////////
|
||||
* using CheapStepper Arduino library v.0.2.0
|
||||
* created by Tyler Henry, 7/2016
|
||||
* ///////////////////////////////////////////
|
||||
*
|
||||
* This sketch illustrates the library's
|
||||
* "non-blocking" move functions -
|
||||
* i.e. you can perform moves with the stepper over time
|
||||
* while still running other code in your loop()
|
||||
*
|
||||
* This can be useful if your Arduino is multi-tasking,
|
||||
* but be careful: if the other code in your loop()
|
||||
* slows down your Arduino, the stepper motor may
|
||||
* slow down or move with a stutter
|
||||
*
|
||||
* //////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
// first, include the library :)
|
||||
|
||||
#include <CheapStepper.h>
|
||||
|
||||
// next, declare the stepper
|
||||
// and connect pins 8,9,10,11 to IN1,IN2,IN3,IN4 on ULN2003 board
|
||||
|
||||
CheapStepper stepper (8,9,10,11);
|
||||
|
||||
|
||||
// let's also create a boolean variable to save the direction of our rotation
|
||||
// and a timer variable to keep track of move times
|
||||
|
||||
bool moveClockwise = true;
|
||||
unsigned long moveStartTime = 0; // this will save the time (millis()) when we started each new move
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
// let's run the stepper at 12rpm (if using 5V power) - the default is ~16 rpm
|
||||
|
||||
stepper.setRpm(12);
|
||||
|
||||
// let's print out the RPM to make sure the setting worked
|
||||
|
||||
Serial.begin(9600);
|
||||
Serial.print("stepper RPM: "); Serial.print(stepper.getRpm());
|
||||
Serial.println();
|
||||
|
||||
// and let's print the delay time (in microseconds) between each step
|
||||
// the delay is based on the RPM setting:
|
||||
// it's how long the stepper will wait before each step
|
||||
|
||||
Serial.print("stepper delay (micros): "); Serial.print(stepper.getDelay());
|
||||
Serial.println(); Serial.println();
|
||||
|
||||
// now let's set up our first move...
|
||||
// let's move a half rotation from the start point
|
||||
|
||||
stepper.newMoveTo(moveClockwise, 2048);
|
||||
/* this is the same as:
|
||||
* stepper.newMoveToDegree(clockwise, 180);
|
||||
* because there are 4096 (default) steps in a full rotation
|
||||
*/
|
||||
moveStartTime = millis(); // let's save the time at which we started this move
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
// we need to call run() during loop()
|
||||
// in order to keep the stepper moving
|
||||
// if we are using non-blocking moves
|
||||
|
||||
stepper.run();
|
||||
|
||||
////////////////////////////////
|
||||
// now the stepper is moving, //
|
||||
// let's do some other stuff! //
|
||||
////////////////////////////////
|
||||
|
||||
// let's check how many steps are left in the current move:
|
||||
|
||||
int stepsLeft = stepper.getStepsLeft();
|
||||
|
||||
// if the current move is done...
|
||||
|
||||
if (stepsLeft == 0){
|
||||
|
||||
// let's print the position of the stepper to serial
|
||||
|
||||
Serial.print("stepper position: "); Serial.print(stepper.getStep());
|
||||
Serial.println();
|
||||
|
||||
// and now let's print the time the move took
|
||||
|
||||
unsigned long timeTook = millis() - moveStartTime; // calculate time elapsed since move start
|
||||
Serial.print("move took (ms): "); Serial.print(timeTook);
|
||||
Serial.println(); Serial.println();
|
||||
|
||||
// let's start a new move in the reverse direction
|
||||
|
||||
moveClockwise = !moveClockwise; // reverse direction
|
||||
stepper.newMoveDegrees (moveClockwise, 180); // move 180 degrees from current position
|
||||
moveStartTime = millis(); // reset move start time
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* cheapStepper_simple.ino
|
||||
* ///////////////////////////////////////////
|
||||
* using CheapStepper Arduino library v.0.2.0
|
||||
* created by Tyler Henry, 7/2016
|
||||
* ///////////////////////////////////////////
|
||||
*
|
||||
* this sketch illustrates basic step() functionality of the library:
|
||||
* the stepper performs a full rotation, pauses 1 second,
|
||||
* then does a full rotation in the other direction, and so on
|
||||
*
|
||||
* //////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
// first, include the library :)
|
||||
|
||||
#include <CheapStepper.h>
|
||||
|
||||
|
||||
CheapStepper stepper;
|
||||
// here we declare our stepper using default pins:
|
||||
// arduino pin <--> pins on ULN2003 board:
|
||||
// 8 <--> IN1
|
||||
// 9 <--> IN2
|
||||
// 10 <--> IN3
|
||||
// 11 <--> IN4
|
||||
|
||||
// let's create a boolean variable to save the direction of our rotation
|
||||
|
||||
boolean moveClockwise = true;
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
// let's just set up a serial connection and test print to the console
|
||||
|
||||
Serial.begin(9600);
|
||||
Serial.println("Ready to start moving!");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
// let's move a full rotation (4096 mini-steps)
|
||||
// we'll go step-by-step using the step() function
|
||||
|
||||
for (int s=0; s<4096; s++){
|
||||
// this will loop 4096 times
|
||||
// 4096 steps = full rotation using default values
|
||||
/* Note:
|
||||
* you could alternatively use 4076 steps...
|
||||
* if you think your 28BYJ-48 stepper's internal gear ratio is 63.68395:1 (measured) rather than 64:1 (advertised)
|
||||
* for more info, see: http://forum.arduino.cc/index.php?topic=71964.15)
|
||||
*/
|
||||
|
||||
// let's move one "step" (of the 4096 per full rotation)
|
||||
|
||||
stepper.step(moveClockwise);
|
||||
/* the direction is based on moveClockwise boolean:
|
||||
* true for clockwise, false for counter-clockwise
|
||||
* -- you could also say stepper.stepCW(); or stepper.stepCCW();
|
||||
*/
|
||||
|
||||
// now let's get the current step position of motor
|
||||
|
||||
int nStep = stepper.getStep();
|
||||
|
||||
// and if it's divisible by 64...
|
||||
|
||||
if (nStep%64==0){
|
||||
|
||||
// let's print the position to the console
|
||||
|
||||
Serial.print("current step position: "); Serial.print(nStep);
|
||||
Serial.println();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// now we've moved 4096 steps
|
||||
|
||||
// let's wait one second
|
||||
|
||||
delay(1000);
|
||||
|
||||
// and switch directions before starting loop() again
|
||||
|
||||
moveClockwise = !moveClockwise;
|
||||
}
|
||||
|
||||
|
BIN
firmware/lib/CheapStepper-master/extras/connections.fzz
Normal file
BIN
firmware/lib/CheapStepper-master/extras/connections.fzz
Normal file
Binary file not shown.
BIN
firmware/lib/CheapStepper-master/extras/connections.png
Normal file
BIN
firmware/lib/CheapStepper-master/extras/connections.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 150 KiB |
Binary file not shown.
Binary file not shown.
@ -0,0 +1,27 @@
|
||||
28BYJ-49 Stepper Motor.fzpz
|
||||
X113647 Stepper Driver Board.fzpz
|
||||
Fritzing parts from https://github.com/tardate/X113647Stepper
|
||||
|
||||
Copyright (c) 2014 Paul Gallagher
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
56
firmware/lib/CheapStepper-master/keywords.txt
Normal file
56
firmware/lib/CheapStepper-master/keywords.txt
Normal file
@ -0,0 +1,56 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For CheapStepper
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
CheapStepper KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
setRpm KEYWORD2
|
||||
set4076StepMode KEYWORD2
|
||||
setTotalSteps KEYWORD2
|
||||
move KEYWORD2
|
||||
moveTo KEYWORD2
|
||||
moveDegrees KEYWORD2
|
||||
moveToDegree KEYWORD2
|
||||
moveCW KEYWORD2
|
||||
moveCCW KEYWORD2
|
||||
moveToCW KEYWORD2
|
||||
moveToCCW KEYWORD2
|
||||
moveDegreesCW KEYWORD2
|
||||
moveDegreesCCW KEYWORD2
|
||||
moveToDegreeCW KEYWORD2
|
||||
moveToDegreeCCW KEYWORD2
|
||||
newMove KEYWORD2
|
||||
newMoveTo KEYWORD2
|
||||
newMoveDegrees KEYWORD2
|
||||
newMoveToDegree KEYWORD2
|
||||
run KEYWORD2
|
||||
stop KEYWORD2
|
||||
newMoveCW KEYWORD2
|
||||
newMoveCCW KEYWORD2
|
||||
newMoveToCW KEYWORD2
|
||||
newMoveToCCW KEYWORD2
|
||||
newMoveDegreesCW KEYWORD2
|
||||
newMoveDegreesCCW KEYWORD2
|
||||
newMoveToDegreeCW KEYWORD2
|
||||
newMoveToDegreeCCW KEYWORD2
|
||||
step KEYWORD2
|
||||
stepCW KEYWORD2
|
||||
stepCCW KEYWORD2
|
||||
getStep KEYWORD2
|
||||
getDelay KEYWORD2
|
||||
getRpm KEYWORD2
|
||||
getPin KEYWORD2
|
||||
getStepsLeft KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
9
firmware/lib/CheapStepper-master/library.properties
Normal file
9
firmware/lib/CheapStepper-master/library.properties
Normal file
@ -0,0 +1,9 @@
|
||||
name=CheapStepper
|
||||
version=0.2
|
||||
author=Tyler Henry
|
||||
maintainer=Tyler Henry <tyler@tylerhenry.com>
|
||||
sentence=A library for the cheap but useful 28BYJ-48 5v stepper motor with ULN2003 driver board
|
||||
paragraph=Library uses half-stepping for fine control (default: 4096 mini-steps per rotation), and supports blocking and non-blocking moves. The total number of steps is also adjustable (e.g. 4076 steps for 63.68395:1 measured gear ratio).
|
||||
category=Device Control
|
||||
url=https://github.com/tyhenry/CheapStepper
|
||||
architectures=*
|
674
firmware/lib/CheapStepper-master/license.txt
Normal file
674
firmware/lib/CheapStepper-master/license.txt
Normal file
@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
BIN
firmware/lib/Rtc-master.zip
Normal file
BIN
firmware/lib/Rtc-master.zip
Normal file
Binary file not shown.
17
firmware/lib/Rtc-master/.gitattributes
vendored
Normal file
17
firmware/lib/Rtc-master/.gitattributes
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
|
||||
# Custom for Visual Studio
|
||||
*.cs diff=csharp
|
||||
|
||||
# Standard to msysgit
|
||||
*.doc diff=astextplain
|
||||
*.DOC diff=astextplain
|
||||
*.docx diff=astextplain
|
||||
*.DOCX diff=astextplain
|
||||
*.dot diff=astextplain
|
||||
*.DOT diff=astextplain
|
||||
*.pdf diff=astextplain
|
||||
*.PDF diff=astextplain
|
||||
*.rtf diff=astextplain
|
||||
*.RTF diff=astextplain
|
43
firmware/lib/Rtc-master/.gitignore
vendored
Normal file
43
firmware/lib/Rtc-master/.gitignore
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# =========================
|
||||
# Operating System Files
|
||||
# =========================
|
||||
|
||||
# OSX
|
||||
# =========================
|
||||
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear on external disk
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
165
firmware/lib/Rtc-master/COPYING
Normal file
165
firmware/lib/Rtc-master/COPYING
Normal file
@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
25
firmware/lib/Rtc-master/README.md
Normal file
25
firmware/lib/Rtc-master/README.md
Normal file
@ -0,0 +1,25 @@
|
||||
# Rtc
|
||||
|
||||
Arduino Real Time Clock library.
|
||||
An RTC library with deep device support.
|
||||
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6AA97KE54UJR4)
|
||||
|
||||
Now supports esp8266.
|
||||
Now supports SoftwareWire library.
|
||||
|
||||
For quick questions jump on Gitter and ask away.
|
||||
[](https://gitter.im/Makuna/Rtc?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
|
||||
For bugs, make sure there isn't an active issue and then create one.
|
||||
|
||||
## Documentation
|
||||
[See Wiki](https://github.com/Makuna/Rtc/wiki)
|
||||
|
||||
## Installing This Library (prefered, you just want to use it)
|
||||
Open the Library Manager and search for "Rtc by Makuna" and install
|
||||
|
||||
## Installing This Library From GitHub (advanced, you want to contribute)
|
||||
Create a directory in your Arduino\Library folder named "Rtc"
|
||||
Clone (Git) this project into that folder.
|
||||
It should now show up in the import list when you restart Arduino IDE.
|
151
firmware/lib/Rtc-master/examples/DS1307_Memory/DS1307_Memory.ino
Normal file
151
firmware/lib/Rtc-master/examples/DS1307_Memory/DS1307_Memory.ino
Normal file
@ -0,0 +1,151 @@
|
||||
|
||||
// CONNECTIONS:
|
||||
// DS1307 SDA --> SDA
|
||||
// DS1307 SCL --> SCL
|
||||
// DS1307 VCC --> 5v
|
||||
// DS1307 GND --> GND
|
||||
|
||||
#define countof(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
/* for software wire use below
|
||||
#include <SoftwareWire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS1307.h>
|
||||
|
||||
SoftwareWire myWire(SDA, SCL);
|
||||
RtcDS1307<SoftwareWire> Rtc(myWire);
|
||||
for software wire use above */
|
||||
|
||||
/* for normal hardware wire use below */
|
||||
#include <Wire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS1307.h>
|
||||
RtcDS1307<TwoWire> Rtc(Wire);
|
||||
/* for normal hardware wire use above */
|
||||
|
||||
|
||||
const char data[] = "what time is it";
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(57600);
|
||||
|
||||
Serial.print("compiled: ");
|
||||
Serial.print(__DATE__);
|
||||
Serial.println(__TIME__);
|
||||
|
||||
//--------RTC SETUP ------------
|
||||
// if you are using ESP-01 then uncomment the line below to reset the pins to
|
||||
// the available pins for SDA, SCL
|
||||
// Wire.begin(0, 2); // due to limited pins, use pin 0 and 2 for SDA, SCL
|
||||
|
||||
Rtc.Begin();
|
||||
|
||||
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
|
||||
printDateTime(compiled);
|
||||
Serial.println();
|
||||
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
|
||||
if (!Rtc.GetIsRunning())
|
||||
{
|
||||
Serial.println("RTC was not actively running, starting now");
|
||||
Rtc.SetIsRunning(true);
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (now < compiled)
|
||||
{
|
||||
Serial.println("RTC is older than compile time! (Updating DateTime)");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
|
||||
// never assume the Rtc was last configured by you, so
|
||||
// just clear them to your needed state
|
||||
Rtc.SetSquareWavePin(DS1307SquareWaveOut_Low);
|
||||
|
||||
/* comment out on a second run to see that the info is stored long term */
|
||||
// Store something in memory on the RTC
|
||||
Rtc.SetMemory(0, 13);
|
||||
uint8_t written = Rtc.SetMemory(13, (const uint8_t*)data, sizeof(data) - 1); // remove the null terminator strings add
|
||||
Rtc.SetMemory(1, written);
|
||||
/* end of comment out section */
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
// Common Cuases:
|
||||
// 1) the battery on the device is low or even missing and the power line was disconnected
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
|
||||
printDateTime(now);
|
||||
Serial.println();
|
||||
|
||||
delay(5000);
|
||||
|
||||
// read data
|
||||
|
||||
// get the offset we stored our data from address zero
|
||||
uint8_t address = Rtc.GetMemory(0);
|
||||
if (address != 13)
|
||||
{
|
||||
Serial.println("address didn't match");
|
||||
}
|
||||
else
|
||||
{
|
||||
// get the size of the data from address 1
|
||||
uint8_t count = Rtc.GetMemory(1);
|
||||
uint8_t buff[20];
|
||||
|
||||
// get our data from the address with the given size
|
||||
uint8_t gotten = Rtc.GetMemory(address, buff, count);
|
||||
|
||||
if (gotten != count ||
|
||||
count != sizeof(data) - 1) // remove the extra null terminator strings add
|
||||
{
|
||||
Serial.print("something didn't match, count = ");
|
||||
Serial.print(count, DEC);
|
||||
Serial.print(", gotten = ");
|
||||
Serial.print(gotten, DEC);
|
||||
Serial.println();
|
||||
}
|
||||
Serial.print("data read (");
|
||||
Serial.print(gotten);
|
||||
Serial.print(") = \"");
|
||||
while (gotten > 0)
|
||||
{
|
||||
Serial.print((char)buff[count - gotten]);
|
||||
gotten--;
|
||||
}
|
||||
Serial.println("\"");
|
||||
}
|
||||
|
||||
|
||||
delay(5000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void printDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
char datestring[20];
|
||||
|
||||
snprintf_P(datestring,
|
||||
countof(datestring),
|
||||
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
|
||||
dt.Month(),
|
||||
dt.Day(),
|
||||
dt.Year(),
|
||||
dt.Hour(),
|
||||
dt.Minute(),
|
||||
dt.Second() );
|
||||
Serial.print(datestring);
|
||||
}
|
||||
|
116
firmware/lib/Rtc-master/examples/DS1307_Simple/DS1307_Simple.ino
Normal file
116
firmware/lib/Rtc-master/examples/DS1307_Simple/DS1307_Simple.ino
Normal file
@ -0,0 +1,116 @@
|
||||
|
||||
// CONNECTIONS:
|
||||
// DS1307 SDA --> SDA
|
||||
// DS1307 SCL --> SCL
|
||||
// DS1307 VCC --> 5v
|
||||
// DS1307 GND --> GND
|
||||
|
||||
/* for software wire use below
|
||||
#include <SoftwareWire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS1307.h>
|
||||
|
||||
SoftwareWire myWire(SDA, SCL);
|
||||
RtcDS1307<SoftwareWire> Rtc(myWire);
|
||||
for software wire use above */
|
||||
|
||||
/* for normal hardware wire use below */
|
||||
#include <Wire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS1307.h>
|
||||
RtcDS1307<TwoWire> Rtc(Wire);
|
||||
/* for normal hardware wire use above */
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(57600);
|
||||
|
||||
Serial.print("compiled: ");
|
||||
Serial.print(__DATE__);
|
||||
Serial.println(__TIME__);
|
||||
|
||||
//--------RTC SETUP ------------
|
||||
// if you are using ESP-01 then uncomment the line below to reset the pins to
|
||||
// the available pins for SDA, SCL
|
||||
// Wire.begin(0, 2); // due to limited pins, use pin 0 and 2 for SDA, SCL
|
||||
|
||||
Rtc.Begin();
|
||||
|
||||
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
|
||||
printDateTime(compiled);
|
||||
Serial.println();
|
||||
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
// Common Cuases:
|
||||
// 1) first time you ran and the device wasn't running yet
|
||||
// 2) the battery on the device is low or even missing
|
||||
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
|
||||
// following line sets the RTC to the date & time this sketch was compiled
|
||||
// it will also reset the valid flag internally unless the Rtc device is
|
||||
// having an issue
|
||||
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
|
||||
if (!Rtc.GetIsRunning())
|
||||
{
|
||||
Serial.println("RTC was not actively running, starting now");
|
||||
Rtc.SetIsRunning(true);
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (now < compiled)
|
||||
{
|
||||
Serial.println("RTC is older than compile time! (Updating DateTime)");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
else if (now > compiled)
|
||||
{
|
||||
Serial.println("RTC is newer than compile time. (this is expected)");
|
||||
}
|
||||
else if (now == compiled)
|
||||
{
|
||||
Serial.println("RTC is the same as compile time! (not expected but all is fine)");
|
||||
}
|
||||
|
||||
// never assume the Rtc was last configured by you, so
|
||||
// just clear them to your needed state
|
||||
Rtc.SetSquareWavePin(DS1307SquareWaveOut_Low);
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
// Common Cuases:
|
||||
// 1) the battery on the device is low or even missing and the power line was disconnected
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
|
||||
printDateTime(now);
|
||||
Serial.println();
|
||||
|
||||
delay(10000); // ten seconds
|
||||
}
|
||||
|
||||
#define countof(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
void printDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
char datestring[20];
|
||||
|
||||
snprintf_P(datestring,
|
||||
countof(datestring),
|
||||
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
|
||||
dt.Month(),
|
||||
dt.Day(),
|
||||
dt.Year(),
|
||||
dt.Hour(),
|
||||
dt.Minute(),
|
||||
dt.Second() );
|
||||
Serial.print(datestring);
|
||||
}
|
||||
|
185
firmware/lib/Rtc-master/examples/DS3231_Alarms/DS3231_Alarms.ino
Normal file
185
firmware/lib/Rtc-master/examples/DS3231_Alarms/DS3231_Alarms.ino
Normal file
@ -0,0 +1,185 @@
|
||||
|
||||
// CONNECTIONS:
|
||||
// DS3231 SDA --> SDA
|
||||
// DS3231 SCL --> SCL
|
||||
// DS3231 VCC --> 3.3v or 5v
|
||||
// DS3231 GND --> GND
|
||||
// SQW ---> (Pin19) Don't forget to pullup (4.7k to 10k to VCC)
|
||||
|
||||
/* for software wire use below
|
||||
#include <SoftwareWire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS3231.h>
|
||||
|
||||
SoftwareWire myWire(SDA, SCL);
|
||||
RtcDS3231<SoftwareWire> Rtc(myWire);
|
||||
for software wire use above */
|
||||
|
||||
/* for normal hardware wire use below */
|
||||
#include <Wire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS3231.h>
|
||||
RtcDS3231<TwoWire> Rtc(Wire);
|
||||
/* for normal hardware wire use above */
|
||||
|
||||
|
||||
// Interrupt Pin Lookup Table
|
||||
// (copied from Arduino Docs)
|
||||
//
|
||||
// CAUTION: The interrupts are Arduino numbers NOT Atmel numbers
|
||||
// and may not match (example, Mega2560 int.4 is actually Atmel Int2)
|
||||
// this is only an issue if you plan to use the lower level interupt features
|
||||
//
|
||||
// Board int.0 int.1 int.2 int.3 int.4 int.5
|
||||
// ---------------------------------------------------------------
|
||||
// Uno, Ethernet 2 3
|
||||
// Mega2560 2 3 21 20 [19] 18
|
||||
// Leonardo 3 2 0 1 7
|
||||
|
||||
#define RtcSquareWavePin 19 // Mega2560
|
||||
#define RtcSquareWaveInterrupt 4 // Mega2560
|
||||
|
||||
// marked volatile so interrupt can safely modify them and
|
||||
// other code can safely read and modify them
|
||||
volatile uint16_t interuptCount = 0;
|
||||
volatile bool interuptFlag = false;
|
||||
|
||||
void InteruptServiceRoutine()
|
||||
{
|
||||
// since this interupted any other running code,
|
||||
// don't do anything that takes long and especially avoid
|
||||
// any communications calls within this routine
|
||||
interuptCount++;
|
||||
interuptFlag = true;
|
||||
}
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(57600);
|
||||
|
||||
// set the interupt pin to input mode
|
||||
pinMode(RtcSquareWavePin, INPUT);
|
||||
|
||||
//--------RTC SETUP ------------
|
||||
// if you are using ESP-01 then uncomment the line below to reset the pins to
|
||||
// the available pins for SDA, SCL
|
||||
// Wire.begin(0, 2); // due to limited pins, use pin 0 and 2 for SDA, SCL
|
||||
|
||||
Rtc.Begin();
|
||||
|
||||
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
|
||||
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
|
||||
if (!Rtc.GetIsRunning())
|
||||
{
|
||||
Serial.println("RTC was not actively running, starting now");
|
||||
Rtc.SetIsRunning(true);
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (now < compiled)
|
||||
{
|
||||
Serial.println("RTC is older than compile time! (Updating DateTime)");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
|
||||
Rtc.Enable32kHzPin(false);
|
||||
Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeAlarmBoth);
|
||||
|
||||
// Alarm 1 set to trigger every day when
|
||||
// the hours, minutes, and seconds match
|
||||
RtcDateTime alarmTime = now + 88; // into the future
|
||||
DS3231AlarmOne alarm1(
|
||||
alarmTime.Day(),
|
||||
alarmTime.Hour(),
|
||||
alarmTime.Minute(),
|
||||
alarmTime.Second(),
|
||||
DS3231AlarmOneControl_HoursMinutesSecondsMatch);
|
||||
Rtc.SetAlarmOne(alarm1);
|
||||
|
||||
// Alarm 2 set to trigger at the top of the minute
|
||||
DS3231AlarmTwo alarm2(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
DS3231AlarmTwoControl_OncePerMinute);
|
||||
Rtc.SetAlarmTwo(alarm2);
|
||||
|
||||
// throw away any old alarm state before we ran
|
||||
Rtc.LatchAlarmsTriggeredFlags();
|
||||
|
||||
// setup external interupt
|
||||
attachInterrupt(RtcSquareWaveInterrupt, InteruptServiceRoutine, FALLING);
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
|
||||
printDateTime(now);
|
||||
Serial.println();
|
||||
|
||||
// we only want to show time every 10 seconds
|
||||
// but we want to show responce to the interupt firing
|
||||
for (int timeCount = 0; timeCount < 20; timeCount++)
|
||||
{
|
||||
if (Alarmed())
|
||||
{
|
||||
Serial.print(">>Interupt Count: ");
|
||||
Serial.print(interuptCount);
|
||||
Serial.println("<<");
|
||||
}
|
||||
delay(500);
|
||||
}
|
||||
}
|
||||
|
||||
bool Alarmed()
|
||||
{
|
||||
bool wasAlarmed = false;
|
||||
if (interuptFlag) // check our flag that gets sets in the interupt
|
||||
{
|
||||
wasAlarmed = true;
|
||||
interuptFlag = false; // reset the flag
|
||||
|
||||
// this gives us which alarms triggered and
|
||||
// then allows for others to trigger again
|
||||
DS3231AlarmFlag flag = Rtc.LatchAlarmsTriggeredFlags();
|
||||
|
||||
if (flag & DS3231AlarmFlag_Alarm1)
|
||||
{
|
||||
Serial.println("alarm one triggered");
|
||||
}
|
||||
if (flag & DS3231AlarmFlag_Alarm2)
|
||||
{
|
||||
Serial.println("alarm two triggered");
|
||||
}
|
||||
}
|
||||
return wasAlarmed;
|
||||
}
|
||||
|
||||
#define countof(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
void printDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
char datestring[20];
|
||||
|
||||
snprintf_P(datestring,
|
||||
countof(datestring),
|
||||
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
|
||||
dt.Month(),
|
||||
dt.Day(),
|
||||
dt.Year(),
|
||||
dt.Hour(),
|
||||
dt.Minute(),
|
||||
dt.Second() );
|
||||
Serial.print(datestring);
|
||||
}
|
||||
|
@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{969D9575-C911-4B46-BC8C-88C6A9086115}</ProjectGuid>
|
||||
<RootNamespace>DS3231_Alarms</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
Editor: http://www.visualmicro.com
|
||||
visual micro and the arduino ide ignore this code during compilation. this code is automatically maintained by visualmicro, manual changes to this file will be overwritten
|
||||
the contents of the Visual Micro sketch sub folder can be deleted prior to publishing a project
|
||||
all non-arduino files created by visual micro and all visual studio project or solution files can be freely deleted and are not required to compile a sketch (do not delete your own code!).
|
||||
note: debugger breakpoints are stored in '.sln' or '.asln' files, knowledge of last uploaded breakpoints is stored in the upload.vmps.xml file. Both files are required to continue a previous debug session without needing to compile and upload again
|
||||
|
||||
Hardware: Arduino Mega w/ ATmega2560 (Mega 2560), Platform=avr, Package=arduino
|
||||
*/
|
||||
|
||||
#ifndef _VSARDUINO_H_
|
||||
#define _VSARDUINO_H_
|
||||
#define __AVR_ATmega2560__
|
||||
#define ARDUINO 161
|
||||
#define ARDUINO_MAIN
|
||||
#define __AVR__
|
||||
#define __avr__
|
||||
#define F_CPU 16000000L
|
||||
#define __cplusplus
|
||||
#define GCC_VERSION 40801
|
||||
#define ARDUINO_ARCH_AVR
|
||||
#define ARDUINO_AVR_MEGA2560
|
||||
#define __inline__
|
||||
#define __asm__(x)
|
||||
#define __extension__
|
||||
//#define __ATTR_PURE__
|
||||
//#define __ATTR_CONST__
|
||||
#define __inline__
|
||||
//#define __asm__
|
||||
#define __volatile__
|
||||
#define GCC_VERSION 40801
|
||||
#define volatile(va_arg)
|
||||
|
||||
typedef void *__builtin_va_list;
|
||||
#define __builtin_va_start
|
||||
#define __builtin_va_end
|
||||
//#define __DOXYGEN__
|
||||
#define __attribute__(x)
|
||||
#define NOINLINE __attribute__((noinline))
|
||||
#define prog_void
|
||||
#define PGM_VOID_P int
|
||||
#define NEW_H
|
||||
/*
|
||||
#ifndef __ATTR_CONST__
|
||||
#define __ATTR_CONST__ __attribute__((__const__))
|
||||
#endif
|
||||
|
||||
#ifndef __ATTR_MALLOC__
|
||||
#define __ATTR_MALLOC__ __attribute__((__malloc__))
|
||||
#endif
|
||||
|
||||
#ifndef __ATTR_NORETURN__
|
||||
#define __ATTR_NORETURN__ __attribute__((__noreturn__))
|
||||
#endif
|
||||
|
||||
#ifndef __ATTR_PURE__
|
||||
#define __ATTR_PURE__ __attribute__((__pure__))
|
||||
#endif
|
||||
*/
|
||||
typedef unsigned char byte;
|
||||
extern "C" void __cxa_pure_virtual() {;}
|
||||
|
||||
|
||||
|
||||
#include <arduino.h>
|
||||
#include <pins_arduino.h>
|
||||
#undef F
|
||||
#define F(string_literal) ((const PROGMEM char *)(string_literal))
|
||||
#undef cli
|
||||
#define cli()
|
||||
#define pgm_read_byte(address_short)
|
||||
#define pgm_read_word(address_short)
|
||||
#define pgm_read_word2(address_short)
|
||||
#define digitalPinToPort(P)
|
||||
#define digitalPinToBitMask(P)
|
||||
#define digitalPinToTimer(P)
|
||||
#define analogInPinToBit(P)
|
||||
#define portOutputRegister(P)
|
||||
#define portInputRegister(P)
|
||||
#define portModeRegister(P)
|
||||
#include <DS3231_Alarms.ino>
|
||||
#endif
|
123
firmware/lib/Rtc-master/examples/DS3231_Simple/DS3231_Simple.ino
Normal file
123
firmware/lib/Rtc-master/examples/DS3231_Simple/DS3231_Simple.ino
Normal file
@ -0,0 +1,123 @@
|
||||
|
||||
// CONNECTIONS:
|
||||
// DS3231 SDA --> SDA
|
||||
// DS3231 SCL --> SCL
|
||||
// DS3231 VCC --> 3.3v or 5v
|
||||
// DS3231 GND --> GND
|
||||
|
||||
/* for software wire use below
|
||||
#include <SoftwareWire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS3231.h>
|
||||
|
||||
SoftwareWire myWire(SDA, SCL);
|
||||
RtcDS3231<SoftwareWire> Rtc(myWire);
|
||||
for software wire use above */
|
||||
|
||||
/* for normal hardware wire use below */
|
||||
#include <Wire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS3231.h>
|
||||
RtcDS3231<TwoWire> Rtc(Wire);
|
||||
/* for normal hardware wire use above */
|
||||
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(57600);
|
||||
|
||||
Serial.print("compiled: ");
|
||||
Serial.print(__DATE__);
|
||||
Serial.println(__TIME__);
|
||||
|
||||
//--------RTC SETUP ------------
|
||||
// if you are using ESP-01 then uncomment the line below to reset the pins to
|
||||
// the available pins for SDA, SCL
|
||||
// Wire.begin(0, 2); // due to limited pins, use pin 0 and 2 for SDA, SCL
|
||||
|
||||
Rtc.Begin();
|
||||
|
||||
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
|
||||
printDateTime(compiled);
|
||||
Serial.println();
|
||||
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
// Common Cuases:
|
||||
// 1) first time you ran and the device wasn't running yet
|
||||
// 2) the battery on the device is low or even missing
|
||||
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
|
||||
// following line sets the RTC to the date & time this sketch was compiled
|
||||
// it will also reset the valid flag internally unless the Rtc device is
|
||||
// having an issue
|
||||
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
|
||||
if (!Rtc.GetIsRunning())
|
||||
{
|
||||
Serial.println("RTC was not actively running, starting now");
|
||||
Rtc.SetIsRunning(true);
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (now < compiled)
|
||||
{
|
||||
Serial.println("RTC is older than compile time! (Updating DateTime)");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
else if (now > compiled)
|
||||
{
|
||||
Serial.println("RTC is newer than compile time. (this is expected)");
|
||||
}
|
||||
else if (now == compiled)
|
||||
{
|
||||
Serial.println("RTC is the same as compile time! (not expected but all is fine)");
|
||||
}
|
||||
|
||||
// never assume the Rtc was last configured by you, so
|
||||
// just clear them to your needed state
|
||||
Rtc.Enable32kHzPin(false);
|
||||
Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone);
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
// Common Cuases:
|
||||
// 1) the battery on the device is low or even missing and the power line was disconnected
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
printDateTime(now);
|
||||
Serial.println();
|
||||
|
||||
RtcTemperature temp = Rtc.GetTemperature();
|
||||
temp.Print(Serial);
|
||||
// you may also get the temperature as a float and print it
|
||||
// Serial.print(temp.AsFloatDegC());
|
||||
Serial.println("C");
|
||||
|
||||
delay(10000); // ten seconds
|
||||
}
|
||||
|
||||
#define countof(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
void printDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
char datestring[20];
|
||||
|
||||
snprintf_P(datestring,
|
||||
countof(datestring),
|
||||
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
|
||||
dt.Month(),
|
||||
dt.Day(),
|
||||
dt.Year(),
|
||||
dt.Hour(),
|
||||
dt.Minute(),
|
||||
dt.Second() );
|
||||
Serial.print(datestring);
|
||||
}
|
||||
|
@ -0,0 +1,100 @@
|
||||
|
||||
// CONNECTIONS:
|
||||
// DS3231 SDA --> SDA
|
||||
// DS3231 SCL --> SCL
|
||||
// DS3231 VCC --> 3.3v or 5v
|
||||
// DS3231 GND --> GND
|
||||
|
||||
/* for software wire use below
|
||||
#include <SoftwareWire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS3231.h>
|
||||
|
||||
SoftwareWire myWire(SDA, SCL);
|
||||
RtcDS3231<SoftwareWire> Rtc(myWire);
|
||||
for software wire use above */
|
||||
|
||||
/* for normal hardware wire use below */
|
||||
#include <Wire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS3231.h>
|
||||
RtcDS3231<TwoWire> Rtc(Wire);
|
||||
/* for normal hardware wire use above */
|
||||
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(57600);
|
||||
|
||||
Serial.print("compiled: ");
|
||||
Serial.print(__DATE__);
|
||||
Serial.println(__TIME__);
|
||||
|
||||
//--------RTC SETUP ------------
|
||||
// if you are using ESP-01 then uncomment the line below to reset the pins to
|
||||
// the available pins for SDA, SCL
|
||||
// Wire.begin(0, 2); // due to limited pins, use pin 0 and 2 for SDA, SCL
|
||||
|
||||
Rtc.Begin();
|
||||
|
||||
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
|
||||
printDateTime(compiled);
|
||||
Serial.println();
|
||||
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
|
||||
if (!Rtc.GetIsRunning())
|
||||
{
|
||||
Serial.println("RTC was not actively running, starting now");
|
||||
Rtc.SetIsRunning(true);
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (now < compiled)
|
||||
{
|
||||
Serial.println("RTC is older than compile time! (Updating DateTime)");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
|
||||
// never assume the Rtc was last configured by you, so
|
||||
// just clear them to your needed state
|
||||
Rtc.Enable32kHzPin(false);
|
||||
Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone);
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
|
||||
printDateTime(now);
|
||||
Serial.println();
|
||||
|
||||
for(;;)
|
||||
{
|
||||
Rtc.SetIsRunning(false);
|
||||
Serial.println(">>> Rtc ready for storage <<<");
|
||||
|
||||
delay(10000); // ten seconds
|
||||
}
|
||||
}
|
||||
|
||||
#define countof(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
void printDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
char datestring[20];
|
||||
|
||||
snprintf_P(datestring,
|
||||
countof(datestring),
|
||||
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
|
||||
dt.Month(),
|
||||
dt.Day(),
|
||||
dt.Year(),
|
||||
dt.Hour(),
|
||||
dt.Minute(),
|
||||
dt.Second() );
|
||||
Serial.print(datestring);
|
||||
}
|
||||
|
@ -0,0 +1,204 @@
|
||||
// These tests do not rely on RTC hardware at all
|
||||
|
||||
//#include <Wire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS3231.h>
|
||||
|
||||
void PrintPassFail(bool passed)
|
||||
{
|
||||
if (passed)
|
||||
{
|
||||
Serial.print("passed");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print("failed");
|
||||
}
|
||||
}
|
||||
|
||||
void ComparePrintlnPassFail(RtcTemperature& rtcTemp, float compare)
|
||||
{
|
||||
Serial.print(rtcTemp.AsFloatDegC());
|
||||
Serial.print("C ");
|
||||
PrintPassFail(rtcTemp.AsFloatDegC() == compare);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void ConstructorTests()
|
||||
{
|
||||
// RTC constructors
|
||||
Serial.println("Constructors:");
|
||||
{
|
||||
RtcTemperature temp075Below(0b11111111, 0b01000000); // -0.75
|
||||
ComparePrintlnPassFail(temp075Below, -0.75f);
|
||||
|
||||
RtcTemperature temp050Below(0b11111111, 0b10000000); // -0.5
|
||||
ComparePrintlnPassFail(temp050Below, -0.50f);
|
||||
|
||||
RtcTemperature temp025Below(0b11111111, 0b11000000); // -0.25
|
||||
ComparePrintlnPassFail(temp025Below, -0.25f);
|
||||
|
||||
RtcTemperature tempZero(0b00000000, 0b00000000); // 0.0
|
||||
ComparePrintlnPassFail(tempZero, -0.0f);
|
||||
|
||||
RtcTemperature temp025Above(0b00000000, 0b01000000); // 0.25
|
||||
ComparePrintlnPassFail(temp025Above, 0.25f);
|
||||
|
||||
RtcTemperature temp050Above(0b00000000, 0b10000000); // 0.5
|
||||
ComparePrintlnPassFail(temp050Above, 0.5f);
|
||||
|
||||
RtcTemperature temp075Above(0b00000000, 0b11000000); // 0.75
|
||||
ComparePrintlnPassFail(temp075Above, 0.75f);
|
||||
|
||||
RtcTemperature temp25Above(0b00011001, 0b00000000); // 25.0
|
||||
ComparePrintlnPassFail(temp25Above, 25.0f);
|
||||
|
||||
RtcTemperature temp25Below(0b11100111, 0b00000000); // -25.0
|
||||
ComparePrintlnPassFail(temp25Below, -25.0f);
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
// SameType
|
||||
{
|
||||
Serial.print("same type ");
|
||||
RtcTemperature temp25Below(0b11100111, 0b00000000); // -25.0
|
||||
RtcTemperature test = temp25Below;
|
||||
ComparePrintlnPassFail(test, -25.0f);
|
||||
}
|
||||
|
||||
// CentiDegrees
|
||||
{
|
||||
Serial.print("centi degrees ");
|
||||
RtcTemperature temp025Below(-25); // -0.25
|
||||
ComparePrintlnPassFail(temp025Below, -0.25f);
|
||||
|
||||
Serial.print("centi degrees ");
|
||||
RtcTemperature temp025Above(25); // 0.25
|
||||
ComparePrintlnPassFail(temp025Above, 0.25f);
|
||||
|
||||
Serial.print("centi degrees ");
|
||||
RtcTemperature temp25Below(-2500); // -25.0
|
||||
ComparePrintlnPassFail(temp25Below, -25.0f);
|
||||
|
||||
Serial.print("centi degrees ");
|
||||
RtcTemperature temp25Above(2500); // 25.0
|
||||
ComparePrintlnPassFail(temp25Above, 25.0f);
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void PrintlnExpected(RtcTemperature& temp, uint16_t digits)
|
||||
{
|
||||
Serial.print(" = ");
|
||||
Serial.print(temp.AsFloatDegC(), digits);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void PrintTests()
|
||||
{
|
||||
Serial.println("Prints:");
|
||||
|
||||
RtcTemperature temp25Above(2500);
|
||||
temp25Above.Print(Serial);
|
||||
PrintlnExpected(temp25Above, 2);
|
||||
|
||||
RtcTemperature temp25Below(-2500);
|
||||
temp25Below.Print(Serial);
|
||||
PrintlnExpected(temp25Below, 2);
|
||||
|
||||
RtcTemperature temp025Above(25);
|
||||
temp025Above.Print(Serial);
|
||||
PrintlnExpected(temp025Above, 2);
|
||||
temp025Above.Print(Serial, 1);
|
||||
PrintlnExpected(temp025Above, 1);
|
||||
|
||||
RtcTemperature temp025Below(-25);
|
||||
temp025Below.Print(Serial);
|
||||
PrintlnExpected(temp025Below, 2);
|
||||
temp025Below.Print(Serial, 1);
|
||||
PrintlnExpected(temp025Below, 1);
|
||||
|
||||
RtcTemperature temp050Above(50);
|
||||
temp050Above.Print(Serial);
|
||||
PrintlnExpected(temp050Above, 2);
|
||||
temp050Above.Print(Serial, 0);
|
||||
PrintlnExpected(temp050Above, 0);
|
||||
|
||||
RtcTemperature temp050Below(-50);
|
||||
temp050Below.Print(Serial);
|
||||
PrintlnExpected(temp050Below, 2);
|
||||
temp050Below.Print(Serial, 0);
|
||||
PrintlnExpected(temp050Below, 0);
|
||||
temp050Below.Print(Serial, 2, ',');
|
||||
Serial.println(" == -0,50");
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void MathmaticalOperatorTests()
|
||||
{
|
||||
Serial.println("Mathmaticals:");
|
||||
|
||||
RtcTemperature temp050Below(-50);
|
||||
RtcTemperature temp050Above(50);
|
||||
RtcTemperature temp050Diff(100);
|
||||
RtcTemperature temp050Same(-50);
|
||||
RtcTemperature tempResult;
|
||||
|
||||
Serial.print("equality ");
|
||||
PrintPassFail(temp050Below == temp050Same);
|
||||
Serial.println();
|
||||
|
||||
Serial.print("inequality ");
|
||||
PrintPassFail(temp050Below != temp050Above);
|
||||
Serial.println();
|
||||
|
||||
Serial.print("less than ");
|
||||
PrintPassFail(temp050Below < temp050Above);
|
||||
Serial.println();
|
||||
|
||||
Serial.print("greater than ");
|
||||
PrintPassFail(temp050Above > temp050Below);
|
||||
Serial.println();
|
||||
|
||||
Serial.print("less than ");
|
||||
PrintPassFail(temp050Below <= temp050Above);
|
||||
Serial.print(" or equal ");
|
||||
PrintPassFail(temp050Below <= temp050Same);
|
||||
Serial.println();
|
||||
|
||||
Serial.print("greater than ");
|
||||
PrintPassFail(temp050Above >= temp050Below);
|
||||
Serial.print(" or equal ");
|
||||
PrintPassFail(temp050Below >= temp050Same);
|
||||
Serial.println();
|
||||
|
||||
tempResult = temp050Above - temp050Below;
|
||||
Serial.print("subtraction ");
|
||||
PrintPassFail(tempResult == temp050Diff);
|
||||
Serial.println();
|
||||
|
||||
tempResult = temp050Above + temp050Above;
|
||||
Serial.print("addition ");
|
||||
PrintPassFail(tempResult == temp050Diff);
|
||||
Serial.println();
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
Serial.println();
|
||||
|
||||
ConstructorTests();
|
||||
PrintTests();
|
||||
MathmaticalOperatorTests();
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
delay(500);
|
||||
}
|
||||
|
93
firmware/lib/Rtc-master/keywords.txt
Normal file
93
firmware/lib/Rtc-master/keywords.txt
Normal file
@ -0,0 +1,93 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map RTC
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
DS3231AlarmOne KEYWORD1
|
||||
DS3231AlarmTwo KEYWORD1
|
||||
RtcDS3231 KEYWORD1
|
||||
RtcTemperature KEYWORD1
|
||||
RtcDateTime KEYWORD1
|
||||
DayOfWeek KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
Begin KEYWORD2
|
||||
IsDateTimeValid KEYWORD2
|
||||
GetIsRunning KEYWORD2
|
||||
SetIsRunning KEYWORD2
|
||||
SetDateTime KEYWORD2
|
||||
GetDateTime KEYWORD2
|
||||
GetTemperature KEYWORD2
|
||||
Enable32kHzPin KEYWORD2
|
||||
SetSquareWavePin KEYWORD2
|
||||
SetSquareWavePinClockFrequency KEYWORD2
|
||||
SetAlarmOne KEYWORD2
|
||||
SetAlarmTwo KEYWORD2
|
||||
GetAlarmOne KEYWORD2
|
||||
GetAlarmTwo KEYWORD2
|
||||
LatchAlarmsTriggeredFlags KEYWORD2
|
||||
ForceTemperatureCompensationUpdate KEYWORD2
|
||||
GetAgingOffset KEYWORD2
|
||||
SetAgingOffset KEYWORD2
|
||||
AsFloat KEYWORD2
|
||||
AsWholeDegrees KEYWORD2
|
||||
GetFractional KEYWORD2
|
||||
Year KEYWORD2
|
||||
Month KEYWORD2
|
||||
Day KEYWORD2
|
||||
Hour KEYWORD2
|
||||
Minute KEYWORD2
|
||||
Second KEYWORD2
|
||||
DayOfWeek KEYWORD2
|
||||
TotalSeconds KEYWORD2
|
||||
DayOf KEYWORD2
|
||||
ControlFlags KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
||||
DS3231SquareWaveClock_1Hz LITERAL1
|
||||
DS3231SquareWaveClock_1kHz LITERAL1
|
||||
DS3231SquareWaveClock_4kHz LITERAL1
|
||||
DS3231SquareWaveClock_8kHz LITERAL1
|
||||
DS3231SquareWavePin_ModeNone LITERAL1
|
||||
DS3231SquareWavePin_ModeBatteryBackup LITERAL1
|
||||
DS3231SquareWavePin_ModeClock LITERAL1
|
||||
DS3231SquareWavePin_ModeAlarmOne LITERAL1
|
||||
DS3231SquareWavePin_ModeAlarmTwo LITERAL1
|
||||
DS3231SquareWavePin_ModeAlarmBoth LITERAL1
|
||||
DS3231AlarmOneControl_HoursMinutesSecondsDayOfMonthMatch LITERAL1
|
||||
DS3231AlarmOneControl_OncePerSecond LITERAL1
|
||||
DS3231AlarmOneControl_SecondsMatch LITERAL1
|
||||
DS3231AlarmOneControl_MinutesSecondsMatch LITERAL1
|
||||
DS3231AlarmOneControl_HoursMinutesSecondsMatch LITERAL1
|
||||
DS3231AlarmOneControl_HoursMinutesSecondsDayOfWeekMatch LITERAL1
|
||||
DS3231AlarmTwoControl_HoursMinutesDayOfMonthMatch LITERAL1
|
||||
DS3231AlarmTwoControl_OncePerMinute LITERAL1
|
||||
DS3231AlarmTwoControl_MinutesMatch LITERAL1
|
||||
DS3231AlarmTwoControl_HoursMinutesMatch LITERAL1
|
||||
DS3231AlarmTwoControl_HoursMinutesDayOfWeekMatch LITERAL1
|
||||
DS3231AlarmFlag_Alarm1 LITERAL1
|
||||
DS3231AlarmFlag_Alarm2 LITERAL1
|
||||
DS3231AlarmFlag_AlarmBoth LITERAL1
|
||||
DS1307SquareWaveOut_1Hz LITERAL1
|
||||
DS1307SquareWaveOut_4kHz LITERAL1
|
||||
DS1307SquareWaveOut_8kHz LITERAL1
|
||||
DS1307SquareWaveOut_32kHz LITERAL1
|
||||
DS1307SquareWaveOut_High LITERAL1
|
||||
DS1307SquareWaveOut_Low LITERAL1
|
||||
DayOfWeek_Sunday LITERAL1
|
||||
DayOfWeek_Monday LITERAL1
|
||||
DayOfWeek_Tuesday LITERAL1
|
||||
DayOfWeek_Wednesday LITERAL1
|
||||
DayOfWeek_Thursday LITERAL1
|
||||
DayOfWeek_Friday LITERAL1
|
||||
DayOfWeek_Saturday LITERAL1
|
||||
|
14
firmware/lib/Rtc-master/library.json
Normal file
14
firmware/lib/Rtc-master/library.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "RTC",
|
||||
"keywords": "RTC, DS1307, DS3231, clock",
|
||||
"description": "A library that makes interfacing DS1307 and DS3231 Real Time Clock modules easy.",
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/Makuna/Rtc.git"
|
||||
},
|
||||
"version": "2.1.0",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*"
|
||||
}
|
||||
|
9
firmware/lib/Rtc-master/library.properties
Normal file
9
firmware/lib/Rtc-master/library.properties
Normal file
@ -0,0 +1,9 @@
|
||||
name=Rtc by Makuna
|
||||
version=2.1.0
|
||||
author=Michael C. Miller (makuna@live.com)
|
||||
maintainer=Michael C. Miller (makuna@live.com)
|
||||
sentence=A library that makes interfacing DS1307 and DS3231 Real Time Clock modules easy.
|
||||
paragraph=Includes deep support of module features, including temperature, alarms and memory storage if present. Tested on esp8266.
|
||||
category=Device Control
|
||||
url=https://github.com/Makuna/Rtc/wiki
|
||||
architectures=*
|
225
firmware/lib/Rtc-master/src/RtcDS1307.h
Normal file
225
firmware/lib/Rtc-master/src/RtcDS1307.h
Normal file
@ -0,0 +1,225 @@
|
||||
|
||||
|
||||
#ifndef __RTCDS1307_H__
|
||||
#define __RTCDS1307_H__
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "RtcDateTime.h"
|
||||
#include "RtcUtility.h"
|
||||
|
||||
//I2C Slave Address
|
||||
const uint8_t DS1307_ADDRESS = 0x68;
|
||||
|
||||
//DS1307 Register Addresses
|
||||
const uint8_t DS1307_REG_TIMEDATE = 0x00;
|
||||
const uint8_t DS1307_REG_STATUS = 0x00;
|
||||
const uint8_t DS1307_REG_CONTROL = 0x07;
|
||||
const uint8_t DS1307_REG_RAMSTART = 0x08;
|
||||
const uint8_t DS1307_REG_RAMEND = 0x3f;
|
||||
const uint8_t DS1307_REG_RAMSIZE = DS1307_REG_RAMEND - DS1307_REG_RAMSTART;
|
||||
|
||||
//DS1307 Register Data Size if not just 1
|
||||
const uint8_t DS1307_REG_TIMEDATE_SIZE = 7;
|
||||
|
||||
// DS1307 Control Register Bits
|
||||
const uint8_t DS1307_RS0 = 0;
|
||||
const uint8_t DS1307_RS1 = 1;
|
||||
const uint8_t DS1307_SQWE = 4;
|
||||
const uint8_t DS1307_OUT = 7;
|
||||
|
||||
// DS1307 Status Register Bits
|
||||
const uint8_t DS1307_CH = 7;
|
||||
|
||||
enum DS1307SquareWaveOut
|
||||
{
|
||||
DS1307SquareWaveOut_1Hz = 0b00010000,
|
||||
DS1307SquareWaveOut_4kHz = 0b00010001,
|
||||
DS1307SquareWaveOut_8kHz = 0b00010010,
|
||||
DS1307SquareWaveOut_32kHz = 0b00010011,
|
||||
DS1307SquareWaveOut_High = 0b10000000,
|
||||
DS1307SquareWaveOut_Low = 0b00000000,
|
||||
};
|
||||
|
||||
template<class T_WIRE_METHOD> class RtcDS1307
|
||||
{
|
||||
public:
|
||||
RtcDS1307(T_WIRE_METHOD& wire) :
|
||||
_wire(wire)
|
||||
{
|
||||
}
|
||||
|
||||
void Begin()
|
||||
{
|
||||
_wire.begin();
|
||||
}
|
||||
|
||||
bool IsDateTimeValid()
|
||||
{
|
||||
return GetIsRunning();
|
||||
}
|
||||
|
||||
bool GetIsRunning()
|
||||
{
|
||||
uint8_t sreg = getReg(DS1307_REG_STATUS);
|
||||
return !(sreg & _BV(DS1307_CH));
|
||||
}
|
||||
|
||||
void SetIsRunning(bool isRunning)
|
||||
{
|
||||
uint8_t sreg = getReg(DS1307_REG_STATUS);
|
||||
if (isRunning)
|
||||
{
|
||||
sreg &= ~_BV(DS1307_CH);
|
||||
}
|
||||
else
|
||||
{
|
||||
sreg |= _BV(DS1307_CH);
|
||||
}
|
||||
setReg(DS1307_REG_STATUS, sreg);
|
||||
}
|
||||
|
||||
void SetDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
// retain running state
|
||||
uint8_t sreg = getReg(DS1307_REG_STATUS) & _BV(DS1307_CH);
|
||||
|
||||
// set the date time
|
||||
_wire.beginTransmission(DS1307_ADDRESS);
|
||||
_wire.write(DS1307_REG_TIMEDATE);
|
||||
|
||||
_wire.write(Uint8ToBcd(dt.Second()) | sreg);
|
||||
_wire.write(Uint8ToBcd(dt.Minute()));
|
||||
_wire.write(Uint8ToBcd(dt.Hour())); // 24 hour mode only
|
||||
|
||||
// RTC Hardware Day of Week is 1-7, 1 = Monday
|
||||
// convert our Day of Week to Rtc Day of Week
|
||||
uint8_t rtcDow = RtcDateTime::ConvertDowToRtc(dt.DayOfWeek());
|
||||
|
||||
_wire.write(Uint8ToBcd(rtcDow));
|
||||
_wire.write(Uint8ToBcd(dt.Day()));
|
||||
_wire.write(Uint8ToBcd(dt.Month()));
|
||||
_wire.write(Uint8ToBcd(dt.Year() - 2000));
|
||||
|
||||
_wire.endTransmission();
|
||||
}
|
||||
|
||||
RtcDateTime GetDateTime()
|
||||
{
|
||||
_wire.beginTransmission(DS1307_ADDRESS);
|
||||
_wire.write(DS1307_REG_TIMEDATE);
|
||||
_wire.endTransmission();
|
||||
|
||||
_wire.requestFrom(DS1307_ADDRESS, DS1307_REG_TIMEDATE_SIZE);
|
||||
uint8_t second = BcdToUint8(_wire.read() & 0x7F);
|
||||
uint8_t minute = BcdToUint8(_wire.read());
|
||||
uint8_t hour = BcdToBin24Hour(_wire.read());
|
||||
|
||||
_wire.read(); // throwing away day of week as we calculate it
|
||||
|
||||
uint8_t dayOfMonth = BcdToUint8(_wire.read());
|
||||
uint8_t month = BcdToUint8(_wire.read());
|
||||
uint16_t year = BcdToUint8(_wire.read()) + 2000;
|
||||
|
||||
return RtcDateTime(year, month, dayOfMonth, hour, minute, second);
|
||||
}
|
||||
|
||||
void SetMemory(uint8_t memoryAddress, uint8_t value)
|
||||
{
|
||||
uint8_t address = memoryAddress + DS1307_REG_RAMSTART;
|
||||
if (address <= DS1307_REG_RAMEND)
|
||||
{
|
||||
setReg(address, value);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t GetMemory(uint8_t memoryAddress)
|
||||
{
|
||||
uint8_t value = 0;
|
||||
uint8_t address = memoryAddress + DS1307_REG_RAMSTART;
|
||||
if (address <= DS1307_REG_RAMEND)
|
||||
{
|
||||
value = getReg(address);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
uint8_t SetMemory(uint8_t memoryAddress, const uint8_t* pValue, uint8_t countBytes)
|
||||
{
|
||||
uint8_t address = memoryAddress + DS1307_REG_RAMSTART;
|
||||
uint8_t countWritten = 0;
|
||||
if (address <= DS1307_REG_RAMEND)
|
||||
{
|
||||
_wire.beginTransmission(DS1307_ADDRESS);
|
||||
_wire.write(address);
|
||||
|
||||
while (countBytes > 0 && address <= DS1307_REG_RAMEND)
|
||||
{
|
||||
_wire.write(*pValue++);
|
||||
address++;
|
||||
countBytes--;
|
||||
countWritten++;
|
||||
}
|
||||
|
||||
_wire.endTransmission();
|
||||
}
|
||||
return countWritten;
|
||||
}
|
||||
|
||||
uint8_t GetMemory(uint8_t memoryAddress, uint8_t* pValue, uint8_t countBytes)
|
||||
{
|
||||
uint8_t address = memoryAddress + DS1307_REG_RAMSTART;
|
||||
uint8_t countRead = 0;
|
||||
if (address <= DS1307_REG_RAMEND)
|
||||
{
|
||||
if (countBytes > DS1307_REG_RAMSIZE)
|
||||
{
|
||||
countBytes = DS1307_REG_RAMSIZE;
|
||||
}
|
||||
|
||||
_wire.beginTransmission(DS1307_ADDRESS);
|
||||
_wire.write(address);
|
||||
_wire.endTransmission();
|
||||
|
||||
_wire.requestFrom(DS1307_ADDRESS, countBytes);
|
||||
|
||||
while (countBytes-- > 0)
|
||||
{
|
||||
*pValue++ = _wire.read();
|
||||
countRead++;
|
||||
}
|
||||
}
|
||||
|
||||
return countRead;
|
||||
}
|
||||
|
||||
void SetSquareWavePin(DS1307SquareWaveOut pinMode)
|
||||
{
|
||||
setReg(DS1307_REG_CONTROL, pinMode);
|
||||
}
|
||||
|
||||
private:
|
||||
T_WIRE_METHOD& _wire;
|
||||
|
||||
uint8_t getReg(uint8_t regAddress)
|
||||
{
|
||||
_wire.beginTransmission(DS1307_ADDRESS);
|
||||
_wire.write(regAddress);
|
||||
_wire.endTransmission();
|
||||
|
||||
// control register
|
||||
_wire.requestFrom(DS1307_ADDRESS, (uint8_t)1);
|
||||
|
||||
uint8_t regValue = _wire.read();
|
||||
return regValue;
|
||||
}
|
||||
|
||||
void setReg(uint8_t regAddress, uint8_t regValue)
|
||||
{
|
||||
_wire.beginTransmission(DS1307_ADDRESS);
|
||||
_wire.write(regAddress);
|
||||
_wire.write(regValue);
|
||||
_wire.endTransmission();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __RTCDS1307_H__
|
576
firmware/lib/Rtc-master/src/RtcDS3231.h
Normal file
576
firmware/lib/Rtc-master/src/RtcDS3231.h
Normal file
@ -0,0 +1,576 @@
|
||||
|
||||
|
||||
#ifndef __RTCDS3231_H__
|
||||
#define __RTCDS3231_H__
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "RtcDateTime.h"
|
||||
#include "RtcTemperature.h"
|
||||
#include "RtcUtility.h"
|
||||
|
||||
|
||||
//I2C Slave Address
|
||||
const uint8_t DS3231_ADDRESS = 0x68;
|
||||
|
||||
//DS3231 Register Addresses
|
||||
const uint8_t DS3231_REG_TIMEDATE = 0x00;
|
||||
const uint8_t DS3231_REG_ALARMONE = 0x07;
|
||||
const uint8_t DS3231_REG_ALARMTWO = 0x0B;
|
||||
|
||||
const uint8_t DS3231_REG_CONTROL = 0x0E;
|
||||
const uint8_t DS3231_REG_STATUS = 0x0F;
|
||||
const uint8_t DS3231_REG_AGING = 0x10;
|
||||
|
||||
const uint8_t DS3231_REG_TEMP = 0x11;
|
||||
|
||||
//DS3231 Register Data Size if not just 1
|
||||
const uint8_t DS3231_REG_TIMEDATE_SIZE = 7;
|
||||
const uint8_t DS3231_REG_ALARMONE_SIZE = 4;
|
||||
const uint8_t DS3231_REG_ALARMTWO_SIZE = 3;
|
||||
|
||||
const uint8_t DS3231_REG_TEMP_SIZE = 2;
|
||||
|
||||
// DS3231 Control Register Bits
|
||||
const uint8_t DS3231_A1IE = 0;
|
||||
const uint8_t DS3231_A2IE = 1;
|
||||
const uint8_t DS3231_INTCN = 2;
|
||||
const uint8_t DS3231_RS1 = 3;
|
||||
const uint8_t DS3231_RS2 = 4;
|
||||
const uint8_t DS3231_CONV = 5;
|
||||
const uint8_t DS3231_BBSQW = 6;
|
||||
const uint8_t DS3231_EOSC = 7;
|
||||
const uint8_t DS3231_AIEMASK = (_BV(DS3231_A1IE) | _BV(DS3231_A2IE));
|
||||
const uint8_t DS3231_RSMASK = (_BV(DS3231_RS1) | _BV(DS3231_RS2));
|
||||
|
||||
// DS3231 Status Register Bits
|
||||
const uint8_t DS3231_A1F = 0;
|
||||
const uint8_t DS3231_A2F = 1;
|
||||
const uint8_t DS3231_BSY = 2;
|
||||
const uint8_t DS3231_EN32KHZ = 3;
|
||||
const uint8_t DS3231_OSF = 7;
|
||||
const uint8_t DS3231_AIFMASK = (_BV(DS3231_A1F) | _BV(DS3231_A2F));
|
||||
|
||||
|
||||
// seconds accuracy
|
||||
enum DS3231AlarmOneControl
|
||||
{
|
||||
// bit order: A1M4 DY/DT A1M3 A1M2 A1M1
|
||||
DS3231AlarmOneControl_HoursMinutesSecondsDayOfMonthMatch = 0x00,
|
||||
DS3231AlarmOneControl_OncePerSecond = 0x17,
|
||||
DS3231AlarmOneControl_SecondsMatch = 0x16,
|
||||
DS3231AlarmOneControl_MinutesSecondsMatch = 0x14,
|
||||
DS3231AlarmOneControl_HoursMinutesSecondsMatch = 0x10,
|
||||
DS3231AlarmOneControl_HoursMinutesSecondsDayOfWeekMatch = 0x08,
|
||||
};
|
||||
|
||||
class DS3231AlarmOne
|
||||
{
|
||||
public:
|
||||
DS3231AlarmOne( uint8_t dayOf,
|
||||
uint8_t hour,
|
||||
uint8_t minute,
|
||||
uint8_t second,
|
||||
DS3231AlarmOneControl controlFlags) :
|
||||
_flags(controlFlags),
|
||||
_dayOf(dayOf),
|
||||
_hour(hour),
|
||||
_minute(minute),
|
||||
_second(second)
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t DayOf() const
|
||||
{
|
||||
return _dayOf;
|
||||
}
|
||||
|
||||
uint8_t Hour() const
|
||||
{
|
||||
return _hour;
|
||||
}
|
||||
|
||||
uint8_t Minute() const
|
||||
{
|
||||
return _minute;
|
||||
}
|
||||
|
||||
uint8_t Second() const
|
||||
{
|
||||
return _second;
|
||||
}
|
||||
|
||||
DS3231AlarmOneControl ControlFlags() const
|
||||
{
|
||||
return _flags;
|
||||
}
|
||||
|
||||
bool operator == (const DS3231AlarmOne& other) const
|
||||
{
|
||||
return (_dayOf == other._dayOf &&
|
||||
_hour == other._hour &&
|
||||
_minute == other._minute &&
|
||||
_second == other._second &&
|
||||
_flags == other._flags);
|
||||
}
|
||||
|
||||
bool operator != (const DS3231AlarmOne& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
protected:
|
||||
DS3231AlarmOneControl _flags;
|
||||
|
||||
uint8_t _dayOf;
|
||||
uint8_t _hour;
|
||||
uint8_t _minute;
|
||||
uint8_t _second;
|
||||
};
|
||||
|
||||
// minutes accuracy
|
||||
enum DS3231AlarmTwoControl
|
||||
{
|
||||
// bit order: A2M4 DY/DT A2M3 A2M2
|
||||
DS3231AlarmTwoControl_HoursMinutesDayOfMonthMatch = 0x00,
|
||||
DS3231AlarmTwoControl_OncePerMinute = 0x0b,
|
||||
DS3231AlarmTwoControl_MinutesMatch = 0x0a,
|
||||
DS3231AlarmTwoControl_HoursMinutesMatch = 0x08,
|
||||
DS3231AlarmTwoControl_HoursMinutesDayOfWeekMatch = 0x04,
|
||||
};
|
||||
|
||||
class DS3231AlarmTwo
|
||||
{
|
||||
public:
|
||||
DS3231AlarmTwo( uint8_t dayOf,
|
||||
uint8_t hour,
|
||||
uint8_t minute,
|
||||
DS3231AlarmTwoControl controlFlags) :
|
||||
_flags(controlFlags),
|
||||
_dayOf(dayOf),
|
||||
_hour(hour),
|
||||
_minute(minute)
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t DayOf() const
|
||||
{
|
||||
return _dayOf;
|
||||
}
|
||||
|
||||
uint8_t Hour() const
|
||||
{
|
||||
return _hour;
|
||||
}
|
||||
|
||||
uint8_t Minute() const
|
||||
{
|
||||
return _minute;
|
||||
}
|
||||
|
||||
DS3231AlarmTwoControl ControlFlags() const
|
||||
{
|
||||
return _flags;
|
||||
}
|
||||
|
||||
bool operator == (const DS3231AlarmTwo& other) const
|
||||
{
|
||||
return (_dayOf == other._dayOf &&
|
||||
_hour == other._hour &&
|
||||
_minute == other._minute &&
|
||||
_flags == other._flags);
|
||||
}
|
||||
|
||||
bool operator != (const DS3231AlarmTwo& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
protected:
|
||||
DS3231AlarmTwoControl _flags;
|
||||
|
||||
uint8_t _dayOf;
|
||||
uint8_t _hour;
|
||||
uint8_t _minute;
|
||||
};
|
||||
|
||||
|
||||
enum DS3231SquareWaveClock
|
||||
{
|
||||
DS3231SquareWaveClock_1Hz = 0b00000000,
|
||||
DS3231SquareWaveClock_1kHz = 0b00001000,
|
||||
DS3231SquareWaveClock_4kHz = 0b00010000,
|
||||
DS3231SquareWaveClock_8kHz = 0b00011000,
|
||||
};
|
||||
|
||||
enum DS3231SquareWavePinMode
|
||||
{
|
||||
DS3231SquareWavePin_ModeNone,
|
||||
DS3231SquareWavePin_ModeBatteryBackup,
|
||||
DS3231SquareWavePin_ModeClock,
|
||||
DS3231SquareWavePin_ModeAlarmOne,
|
||||
DS3231SquareWavePin_ModeAlarmTwo,
|
||||
DS3231SquareWavePin_ModeAlarmBoth
|
||||
};
|
||||
|
||||
enum DS3231AlarmFlag
|
||||
{
|
||||
DS3231AlarmFlag_Alarm1 = 0x01,
|
||||
DS3231AlarmFlag_Alarm2 = 0x02,
|
||||
DS3231AlarmFlag_AlarmBoth = 0x03,
|
||||
};
|
||||
|
||||
template<class T_WIRE_METHOD> class RtcDS3231
|
||||
{
|
||||
public:
|
||||
RtcDS3231(T_WIRE_METHOD& wire) :
|
||||
_wire(wire)
|
||||
{
|
||||
}
|
||||
|
||||
void Begin()
|
||||
{
|
||||
_wire.begin();
|
||||
}
|
||||
|
||||
bool IsDateTimeValid()
|
||||
{
|
||||
uint8_t status = getReg(DS3231_REG_STATUS);
|
||||
return !(status & _BV(DS3231_OSF));
|
||||
}
|
||||
|
||||
bool GetIsRunning()
|
||||
{
|
||||
uint8_t creg = getReg(DS3231_REG_CONTROL);
|
||||
return !(creg & _BV(DS3231_EOSC));
|
||||
}
|
||||
|
||||
void SetIsRunning(bool isRunning)
|
||||
{
|
||||
uint8_t creg = getReg(DS3231_REG_CONTROL);
|
||||
if (isRunning)
|
||||
{
|
||||
creg &= ~_BV(DS3231_EOSC);
|
||||
}
|
||||
else
|
||||
{
|
||||
creg |= _BV(DS3231_EOSC);
|
||||
}
|
||||
setReg(DS3231_REG_CONTROL, creg);
|
||||
}
|
||||
|
||||
void SetDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
// clear the invalid flag
|
||||
uint8_t status = getReg(DS3231_REG_STATUS);
|
||||
status &= ~_BV(DS3231_OSF); // clear the flag
|
||||
setReg(DS3231_REG_STATUS, status);
|
||||
|
||||
// set the date time
|
||||
_wire.beginTransmission(DS3231_ADDRESS);
|
||||
_wire.write(DS3231_REG_TIMEDATE);
|
||||
|
||||
_wire.write(Uint8ToBcd(dt.Second()));
|
||||
_wire.write(Uint8ToBcd(dt.Minute()));
|
||||
_wire.write(Uint8ToBcd(dt.Hour())); // 24 hour mode only
|
||||
|
||||
uint8_t year = dt.Year() - 2000;
|
||||
uint8_t centuryFlag = 0;
|
||||
|
||||
if (year >= 100)
|
||||
{
|
||||
year -= 100;
|
||||
centuryFlag = _BV(7);
|
||||
}
|
||||
|
||||
// RTC Hardware Day of Week is 1-7, 1 = Monday
|
||||
// convert our Day of Week to Rtc Day of Week
|
||||
uint8_t rtcDow = RtcDateTime::ConvertDowToRtc(dt.DayOfWeek());
|
||||
|
||||
_wire.write(Uint8ToBcd(rtcDow));
|
||||
|
||||
_wire.write(Uint8ToBcd(dt.Day()));
|
||||
_wire.write(Uint8ToBcd(dt.Month()) | centuryFlag);
|
||||
_wire.write(Uint8ToBcd(year));
|
||||
|
||||
_wire.endTransmission();
|
||||
}
|
||||
|
||||
RtcDateTime GetDateTime()
|
||||
{
|
||||
_wire.beginTransmission(DS3231_ADDRESS);
|
||||
_wire.write(DS3231_REG_TIMEDATE);
|
||||
_wire.endTransmission();
|
||||
|
||||
_wire.requestFrom(DS3231_ADDRESS, DS3231_REG_TIMEDATE_SIZE);
|
||||
uint8_t second = BcdToUint8(_wire.read() & 0x7F);
|
||||
uint8_t minute = BcdToUint8(_wire.read());
|
||||
uint8_t hour = BcdToBin24Hour(_wire.read());
|
||||
|
||||
_wire.read(); // throwing away day of week as we calculate it
|
||||
|
||||
uint8_t dayOfMonth = BcdToUint8(_wire.read());
|
||||
uint8_t monthRaw = _wire.read();
|
||||
uint16_t year = BcdToUint8(_wire.read()) + 2000;
|
||||
|
||||
if (monthRaw & _BV(7)) // century wrap flag
|
||||
{
|
||||
year += 100;
|
||||
}
|
||||
uint8_t month = BcdToUint8(monthRaw & 0x7f);
|
||||
|
||||
|
||||
return RtcDateTime(year, month, dayOfMonth, hour, minute, second);
|
||||
}
|
||||
|
||||
RtcTemperature GetTemperature()
|
||||
{
|
||||
_wire.beginTransmission(DS3231_ADDRESS);
|
||||
_wire.write(DS3231_REG_TEMP);
|
||||
_wire.endTransmission();
|
||||
|
||||
// Temperature is represented as a 10-bit code with a resolution
|
||||
// of 1/4th <20>C and is accessable as a signed 16-bit integer at
|
||||
// locations 11h and 12h.
|
||||
//
|
||||
// | r11h | DP | r12h |
|
||||
// Bit: 15 14 13 12 11 10 9 8 . 7 6 5 4 3 2 1 0 -1 -2
|
||||
// s i i i i i i i . f f 0 0 0 0 0 0
|
||||
//
|
||||
// As it takes (8) right-shifts to register the decimal point (DP) to
|
||||
// the right of the 0th bit, the overall word scaling equals 256.
|
||||
//
|
||||
// For example, at +/- 25.25<EFBFBD>C, concatenated registers <r11h:r12h> =
|
||||
// 256 * (+/- 25+(1/4)) = +/- 6464, or 1940h / E6C0h.
|
||||
|
||||
_wire.requestFrom(DS3231_ADDRESS, DS3231_REG_TEMP_SIZE);
|
||||
int8_t r11h = _wire.read(); // MS byte, signed temperature
|
||||
return RtcTemperature( r11h, _wire.read() ); // LS byte is r12h
|
||||
}
|
||||
|
||||
void Enable32kHzPin(bool enable)
|
||||
{
|
||||
uint8_t sreg = getReg(DS3231_REG_STATUS);
|
||||
|
||||
if (enable == true)
|
||||
{
|
||||
sreg |= _BV(DS3231_EN32KHZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
sreg &= ~_BV(DS3231_EN32KHZ);
|
||||
}
|
||||
|
||||
setReg(DS3231_REG_STATUS, sreg);
|
||||
}
|
||||
|
||||
void SetSquareWavePin(DS3231SquareWavePinMode pinMode)
|
||||
{
|
||||
uint8_t creg = getReg(DS3231_REG_CONTROL);
|
||||
|
||||
// clear all relevant bits to a known "off" state
|
||||
creg &= ~(DS3231_AIEMASK | _BV(DS3231_BBSQW));
|
||||
creg |= _BV(DS3231_INTCN); // set INTCN to disables SQW
|
||||
|
||||
switch (pinMode)
|
||||
{
|
||||
case DS3231SquareWavePin_ModeNone:
|
||||
break;
|
||||
|
||||
case DS3231SquareWavePin_ModeBatteryBackup:
|
||||
creg |= _BV(DS3231_BBSQW); // set battery backup flag
|
||||
creg &= ~_BV(DS3231_INTCN); // clear INTCN to enable SQW
|
||||
break;
|
||||
|
||||
case DS3231SquareWavePin_ModeClock:
|
||||
creg &= ~_BV(DS3231_INTCN); // clear INTCN to enable SQW
|
||||
break;
|
||||
|
||||
case DS3231SquareWavePin_ModeAlarmOne:
|
||||
creg |= _BV(DS3231_A1IE);
|
||||
break;
|
||||
|
||||
case DS3231SquareWavePin_ModeAlarmTwo:
|
||||
creg |= _BV(DS3231_A2IE);
|
||||
break;
|
||||
|
||||
case DS3231SquareWavePin_ModeAlarmBoth:
|
||||
creg |= _BV(DS3231_A1IE) | _BV(DS3231_A2IE);
|
||||
break;
|
||||
}
|
||||
|
||||
setReg(DS3231_REG_CONTROL, creg);
|
||||
}
|
||||
|
||||
void SetSquareWavePinClockFrequency(DS3231SquareWaveClock freq)
|
||||
{
|
||||
uint8_t creg = getReg(DS3231_REG_CONTROL);
|
||||
|
||||
creg &= ~DS3231_RSMASK; // Set to 0
|
||||
creg |= (freq & DS3231_RSMASK); // Set freq bits
|
||||
|
||||
setReg(DS3231_REG_CONTROL, creg);
|
||||
}
|
||||
|
||||
|
||||
void SetAlarmOne(const DS3231AlarmOne& alarm)
|
||||
{
|
||||
_wire.beginTransmission(DS3231_ADDRESS);
|
||||
_wire.write(DS3231_REG_ALARMONE);
|
||||
|
||||
_wire.write(Uint8ToBcd(alarm.Second()) | ((alarm.ControlFlags() & 0x01) << 7));
|
||||
_wire.write(Uint8ToBcd(alarm.Minute()) | ((alarm.ControlFlags() & 0x02) << 6));
|
||||
_wire.write(Uint8ToBcd(alarm.Hour()) | ((alarm.ControlFlags() & 0x04) << 5)); // 24 hour mode only
|
||||
|
||||
uint8_t rtcDow = alarm.DayOf();
|
||||
if (alarm.ControlFlags() == DS3231AlarmOneControl_HoursMinutesSecondsDayOfWeekMatch)
|
||||
{
|
||||
rtcDow = RtcDateTime::ConvertDowToRtc(rtcDow);
|
||||
}
|
||||
|
||||
_wire.write(Uint8ToBcd(rtcDow) | ((alarm.ControlFlags() & 0x18) << 3));
|
||||
|
||||
_wire.endTransmission();
|
||||
}
|
||||
|
||||
void SetAlarmTwo(const DS3231AlarmTwo& alarm)
|
||||
{
|
||||
_wire.beginTransmission(DS3231_ADDRESS);
|
||||
_wire.write(DS3231_REG_ALARMTWO);
|
||||
|
||||
_wire.write(Uint8ToBcd(alarm.Minute()) | ((alarm.ControlFlags() & 0x01) << 7));
|
||||
_wire.write(Uint8ToBcd(alarm.Hour()) | ((alarm.ControlFlags() & 0x02) << 6)); // 24 hour mode only
|
||||
|
||||
// convert our Day of Week to Rtc Day of Week if needed
|
||||
uint8_t rtcDow = alarm.DayOf();
|
||||
if (alarm.ControlFlags() == DS3231AlarmTwoControl_HoursMinutesDayOfWeekMatch)
|
||||
{
|
||||
rtcDow = RtcDateTime::ConvertDowToRtc(rtcDow);
|
||||
}
|
||||
|
||||
_wire.write(Uint8ToBcd(rtcDow) | ((alarm.ControlFlags() & 0x0c) << 4));
|
||||
|
||||
_wire.endTransmission();
|
||||
}
|
||||
|
||||
DS3231AlarmOne GetAlarmOne()
|
||||
{
|
||||
_wire.beginTransmission(DS3231_ADDRESS);
|
||||
_wire.write(DS3231_REG_ALARMONE);
|
||||
_wire.endTransmission();
|
||||
|
||||
_wire.requestFrom(DS3231_ADDRESS, DS3231_REG_ALARMONE_SIZE);
|
||||
|
||||
uint8_t raw = _wire.read();
|
||||
uint8_t flags = (raw & 0x80) >> 7;
|
||||
uint8_t second = BcdToUint8(raw & 0x7F);
|
||||
|
||||
raw = _wire.read();
|
||||
flags |= (raw & 0x80) >> 6;
|
||||
uint8_t minute = BcdToUint8(raw & 0x7F);
|
||||
|
||||
raw = _wire.read();
|
||||
flags |= (raw & 0x80) >> 5;
|
||||
uint8_t hour = BcdToBin24Hour(raw & 0x7f);
|
||||
|
||||
raw = _wire.read();
|
||||
flags |= (raw & 0xc0) >> 3;
|
||||
uint8_t dayOf = BcdToUint8(raw & 0x3f);
|
||||
|
||||
if (flags == DS3231AlarmOneControl_HoursMinutesSecondsDayOfWeekMatch)
|
||||
{
|
||||
dayOf = RtcDateTime::ConvertRtcToDow(dayOf);
|
||||
}
|
||||
|
||||
return DS3231AlarmOne(dayOf, hour, minute, second, (DS3231AlarmOneControl)flags);
|
||||
}
|
||||
|
||||
DS3231AlarmTwo GetAlarmTwo()
|
||||
{
|
||||
_wire.beginTransmission(DS3231_ADDRESS);
|
||||
_wire.write(DS3231_REG_ALARMTWO);
|
||||
_wire.endTransmission();
|
||||
|
||||
_wire.requestFrom(DS3231_ADDRESS, DS3231_REG_ALARMTWO_SIZE);
|
||||
|
||||
uint8_t raw = _wire.read();
|
||||
uint8_t flags = (raw & 0x80) >> 7;
|
||||
uint8_t minute = BcdToUint8(raw & 0x7F);
|
||||
|
||||
raw = _wire.read();
|
||||
flags |= (raw & 0x80) >> 6;
|
||||
uint8_t hour = BcdToBin24Hour(raw & 0x7f);
|
||||
|
||||
raw = _wire.read();
|
||||
flags |= (raw & 0xc0) >> 4;
|
||||
uint8_t dayOf = BcdToUint8(raw & 0x3f);
|
||||
|
||||
if (flags == DS3231AlarmTwoControl_HoursMinutesDayOfWeekMatch)
|
||||
{
|
||||
dayOf = RtcDateTime::ConvertRtcToDow(dayOf);
|
||||
}
|
||||
|
||||
return DS3231AlarmTwo(dayOf, hour, minute, (DS3231AlarmTwoControl)flags);
|
||||
}
|
||||
|
||||
// Latch must be called after an alarm otherwise it will not
|
||||
// trigger again
|
||||
DS3231AlarmFlag LatchAlarmsTriggeredFlags()
|
||||
{
|
||||
uint8_t sreg = getReg(DS3231_REG_STATUS);
|
||||
uint8_t alarmFlags = (sreg & DS3231_AIFMASK);
|
||||
sreg &= ~DS3231_AIFMASK; // clear the flags
|
||||
setReg(DS3231_REG_STATUS, sreg);
|
||||
return (DS3231AlarmFlag)alarmFlags;
|
||||
}
|
||||
|
||||
void ForceTemperatureCompensationUpdate(bool block)
|
||||
{
|
||||
uint8_t creg = getReg(DS3231_REG_CONTROL);
|
||||
creg |= _BV(DS3231_CONV); // Write CONV bit
|
||||
setReg(DS3231_REG_CONTROL, creg);
|
||||
|
||||
while (block && (creg & _BV(DS3231_CONV)) != 0)
|
||||
{
|
||||
// Block until CONV is 0
|
||||
creg = getReg(DS3231_REG_CONTROL);
|
||||
}
|
||||
}
|
||||
|
||||
int8_t GetAgingOffset()
|
||||
{
|
||||
return getReg(DS3231_REG_AGING);
|
||||
}
|
||||
|
||||
void SetAgingOffset(int8_t value)
|
||||
{
|
||||
setReg(DS3231_REG_AGING, value);
|
||||
}
|
||||
|
||||
private:
|
||||
T_WIRE_METHOD& _wire;
|
||||
|
||||
uint8_t getReg(uint8_t regAddress)
|
||||
{
|
||||
_wire.beginTransmission(DS3231_ADDRESS);
|
||||
_wire.write(regAddress);
|
||||
_wire.endTransmission();
|
||||
|
||||
// control register
|
||||
_wire.requestFrom(DS3231_ADDRESS, (uint8_t)1);
|
||||
|
||||
uint8_t regValue = _wire.read();
|
||||
return regValue;
|
||||
}
|
||||
|
||||
void setReg(uint8_t regAddress, uint8_t regValue)
|
||||
{
|
||||
_wire.beginTransmission(DS3231_ADDRESS);
|
||||
_wire.write(regAddress);
|
||||
_wire.write(regValue);
|
||||
_wire.endTransmission();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // __RTCDS3231_H__
|
154
firmware/lib/Rtc-master/src/RtcDateTime.cpp
Normal file
154
firmware/lib/Rtc-master/src/RtcDateTime.cpp
Normal file
@ -0,0 +1,154 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "RtcDateTime.h"
|
||||
|
||||
const uint8_t c_daysInMonth[] PROGMEM = { 31,28,31,30,31,30,31,31,30,31,30,31 };
|
||||
|
||||
RtcDateTime::RtcDateTime(uint32_t secondsFrom2000)
|
||||
{
|
||||
_initWithSecondsFrom2000<uint32_t>(secondsFrom2000);
|
||||
}
|
||||
|
||||
|
||||
uint8_t StringToUint8(const char* pString)
|
||||
{
|
||||
uint8_t value = 0;
|
||||
|
||||
// skip leading 0 and spaces
|
||||
while ('0' == *pString || *pString == ' ')
|
||||
{
|
||||
pString++;
|
||||
}
|
||||
|
||||
// calculate number until we hit non-numeral char
|
||||
while ('0' <= *pString && *pString <= '9')
|
||||
{
|
||||
value *= 10;
|
||||
value += *pString - '0';
|
||||
pString++;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
RtcDateTime::RtcDateTime(const char* date, const char* time)
|
||||
{
|
||||
// sample input: date = "Dec 26 2009", time = "12:34:56"
|
||||
_yearFrom2000 = StringToUint8(date + 9);
|
||||
// Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
|
||||
switch (date[0])
|
||||
{
|
||||
case 'J':
|
||||
if ( date[1] == 'a' )
|
||||
_month = 1;
|
||||
else if ( date[2] == 'n' )
|
||||
_month = 6;
|
||||
else
|
||||
_month = 7;
|
||||
break;
|
||||
case 'F':
|
||||
_month = 2;
|
||||
break;
|
||||
case 'A':
|
||||
_month = date[1] == 'p' ? 4 : 8;
|
||||
break;
|
||||
case 'M':
|
||||
_month = date[2] == 'r' ? 3 : 5;
|
||||
break;
|
||||
case 'S':
|
||||
_month = 9;
|
||||
break;
|
||||
case 'O':
|
||||
_month = 10;
|
||||
break;
|
||||
case 'N':
|
||||
_month = 11;
|
||||
break;
|
||||
case 'D':
|
||||
_month = 12;
|
||||
break;
|
||||
}
|
||||
_dayOfMonth = StringToUint8(date + 4);
|
||||
_hour = StringToUint8(time);
|
||||
_minute = StringToUint8(time + 3);
|
||||
_second = StringToUint8(time + 6);
|
||||
}
|
||||
|
||||
template <typename T> T DaysSinceFirstOfYear2000(uint16_t year, uint8_t month, uint8_t dayOfMonth)
|
||||
{
|
||||
T days = dayOfMonth;
|
||||
for (uint8_t indexMonth = 1; indexMonth < month; ++indexMonth)
|
||||
{
|
||||
days += pgm_read_byte(c_daysInMonth + indexMonth - 1);
|
||||
}
|
||||
if (month > 2 && year % 4 == 0)
|
||||
{
|
||||
days++;
|
||||
}
|
||||
return days + 365 * year + (year + 3) / 4 - 1;
|
||||
}
|
||||
|
||||
template <typename T> T SecondsIn(T days, uint8_t hours, uint8_t minutes, uint8_t seconds)
|
||||
{
|
||||
return ((days * 24L + hours) * 60 + minutes) * 60 + seconds;
|
||||
}
|
||||
|
||||
uint8_t RtcDateTime::DayOfWeek() const
|
||||
{
|
||||
uint16_t days = DaysSinceFirstOfYear2000<uint16_t>(_yearFrom2000, _month, _dayOfMonth);
|
||||
return (days + 6) % 7; // Jan 1, 2000 is a Saturday, i.e. returns 6
|
||||
}
|
||||
|
||||
uint32_t RtcDateTime::TotalSeconds() const
|
||||
{
|
||||
uint16_t days = DaysSinceFirstOfYear2000<uint16_t>(_yearFrom2000, _month, _dayOfMonth);
|
||||
return SecondsIn<uint32_t>(days, _hour, _minute, _second);
|
||||
}
|
||||
|
||||
uint64_t RtcDateTime::TotalSeconds64() const
|
||||
{
|
||||
uint32_t days = DaysSinceFirstOfYear2000<uint32_t>(_yearFrom2000, _month, _dayOfMonth);
|
||||
return SecondsIn<uint64_t>(days, _hour, _minute, _second);
|
||||
}
|
||||
|
||||
void RtcDateTime::InitWithIso8601(const char* date)
|
||||
{
|
||||
// sample input: date = "Sat, 26 Dec 2009 12:34:56 GMT"
|
||||
_yearFrom2000 = StringToUint8(date + 13);
|
||||
// Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
|
||||
switch (date[8])
|
||||
{
|
||||
case 'J':
|
||||
if (date[1 + 8] == 'a')
|
||||
_month = 1;
|
||||
else if (date[2 + 8] == 'n')
|
||||
_month = 6;
|
||||
else
|
||||
_month = 7;
|
||||
break;
|
||||
case 'F':
|
||||
_month = 2;
|
||||
break;
|
||||
case 'A':
|
||||
_month = date[1 + 8] == 'p' ? 4 : 8;
|
||||
break;
|
||||
case 'M':
|
||||
_month = date[2 + 8] == 'r' ? 3 : 5;
|
||||
break;
|
||||
case 'S':
|
||||
_month = 9;
|
||||
break;
|
||||
case 'O':
|
||||
_month = 10;
|
||||
break;
|
||||
case 'N':
|
||||
_month = 11;
|
||||
break;
|
||||
case 'D':
|
||||
_month = 12;
|
||||
break;
|
||||
}
|
||||
_dayOfMonth = StringToUint8(date + 5);
|
||||
_hour = StringToUint8(date + 17);
|
||||
_minute = StringToUint8(date + 20);
|
||||
_second = StringToUint8(date + 23);
|
||||
}
|
178
firmware/lib/Rtc-master/src/RtcDateTime.h
Normal file
178
firmware/lib/Rtc-master/src/RtcDateTime.h
Normal file
@ -0,0 +1,178 @@
|
||||
|
||||
|
||||
#ifndef __RTCDATETIME_H__
|
||||
#define __RTCDATETIME_H__
|
||||
|
||||
// ESP32 complains if not included
|
||||
#if defined(ARDUINO_ARCH_ESP32)
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
enum DayOfWeek
|
||||
{
|
||||
DayOfWeek_Sunday = 0,
|
||||
DayOfWeek_Monday,
|
||||
DayOfWeek_Tuesday,
|
||||
DayOfWeek_Wednesday,
|
||||
DayOfWeek_Thursday,
|
||||
DayOfWeek_Friday,
|
||||
DayOfWeek_Saturday,
|
||||
};
|
||||
|
||||
const uint16_t c_OriginYear = 2000;
|
||||
const uint32_t c_Epoch32OfOriginYear = 946684800;
|
||||
extern const uint8_t c_daysInMonth[] PROGMEM;
|
||||
|
||||
class RtcDateTime
|
||||
{
|
||||
public:
|
||||
RtcDateTime(uint32_t secondsFrom2000 = 0);
|
||||
RtcDateTime(uint16_t year,
|
||||
uint8_t month,
|
||||
uint8_t dayOfMonth,
|
||||
uint8_t hour,
|
||||
uint8_t minute,
|
||||
uint8_t second) :
|
||||
_yearFrom2000((year >= c_OriginYear) ? year - c_OriginYear : year),
|
||||
_month(month),
|
||||
_dayOfMonth(dayOfMonth),
|
||||
_hour(hour),
|
||||
_minute(minute),
|
||||
_second(second)
|
||||
{
|
||||
}
|
||||
|
||||
// RtcDateTime compileDateTime(__DATE__, __TIME__);
|
||||
RtcDateTime(const char* date, const char* time);
|
||||
|
||||
uint16_t Year() const
|
||||
{
|
||||
return c_OriginYear + _yearFrom2000;
|
||||
}
|
||||
uint8_t Month() const
|
||||
{
|
||||
return _month;
|
||||
}
|
||||
uint8_t Day() const
|
||||
{
|
||||
return _dayOfMonth;
|
||||
}
|
||||
uint8_t Hour() const
|
||||
{
|
||||
return _hour;
|
||||
}
|
||||
uint8_t Minute() const
|
||||
{
|
||||
return _minute;
|
||||
}
|
||||
uint8_t Second() const
|
||||
{
|
||||
return _second;
|
||||
}
|
||||
// 0 = Sunday, 1 = Monday, ... 6 = Saturday
|
||||
uint8_t DayOfWeek() const;
|
||||
|
||||
// 32-bit times as seconds since 1/1/2000
|
||||
uint32_t TotalSeconds() const;
|
||||
uint64_t TotalSeconds64() const;
|
||||
|
||||
// add seconds
|
||||
void operator += (uint32_t seconds)
|
||||
{
|
||||
RtcDateTime after = RtcDateTime( TotalSeconds() + seconds );
|
||||
*this = after;
|
||||
}
|
||||
|
||||
// remove seconds
|
||||
void operator -= (uint32_t seconds)
|
||||
{
|
||||
RtcDateTime before = RtcDateTime( TotalSeconds() - seconds );
|
||||
*this = before;
|
||||
}
|
||||
|
||||
// allows for comparisons to just work (==, <, >, <=, >=, !=)
|
||||
operator uint32_t() const
|
||||
{
|
||||
return TotalSeconds();
|
||||
}
|
||||
|
||||
// Epoch32 support
|
||||
uint32_t Epoch32Time() const
|
||||
{
|
||||
return TotalSeconds() + c_Epoch32OfOriginYear;
|
||||
}
|
||||
void InitWithEpoch32Time(uint32_t time)
|
||||
{
|
||||
_initWithSecondsFrom2000<uint32_t>(time - c_Epoch32OfOriginYear);
|
||||
}
|
||||
|
||||
// Epoch64 support
|
||||
uint64_t Epoch64Time() const
|
||||
{
|
||||
return TotalSeconds64() + c_Epoch32OfOriginYear;
|
||||
}
|
||||
void InitWithEpoch64Time(uint64_t time)
|
||||
{
|
||||
_initWithSecondsFrom2000<uint64_t>(time - c_Epoch32OfOriginYear);
|
||||
}
|
||||
|
||||
void InitWithIso8601(const char* date);
|
||||
|
||||
|
||||
// convert our Day of Week to Rtc Day of Week
|
||||
// RTC Hardware Day of Week is 1-7, 1 = Monday
|
||||
static uint8_t ConvertDowToRtc(uint8_t dow)
|
||||
{
|
||||
if (dow == 0)
|
||||
{
|
||||
dow = 7;
|
||||
}
|
||||
return dow;
|
||||
}
|
||||
|
||||
// convert Rtc Day of Week to our Day of Week
|
||||
static uint8_t ConvertRtcToDow(uint8_t rtcDow)
|
||||
{
|
||||
return (rtcDow % 7);
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t _yearFrom2000;
|
||||
uint8_t _month;
|
||||
uint8_t _dayOfMonth;
|
||||
uint8_t _hour;
|
||||
uint8_t _minute;
|
||||
uint8_t _second;
|
||||
|
||||
template <typename T> void _initWithSecondsFrom2000(T secondsFrom2000)
|
||||
{
|
||||
_second = secondsFrom2000 % 60;
|
||||
T timeFrom2000 = secondsFrom2000 / 60;
|
||||
_minute = timeFrom2000 % 60;
|
||||
timeFrom2000 /= 60;
|
||||
_hour = timeFrom2000 % 24;
|
||||
T days = timeFrom2000 / 24;
|
||||
T leapDays;
|
||||
|
||||
for (_yearFrom2000 = 0;; ++_yearFrom2000)
|
||||
{
|
||||
leapDays = (_yearFrom2000 % 4 == 0) ? 1 : 0;
|
||||
if (days < 365U + leapDays)
|
||||
break;
|
||||
days -= 365 + leapDays;
|
||||
}
|
||||
for (_month = 1;; ++_month)
|
||||
{
|
||||
uint8_t daysPerMonth = pgm_read_byte(c_daysInMonth + _month - 1);
|
||||
if (leapDays && _month == 2)
|
||||
daysPerMonth++;
|
||||
if (days < daysPerMonth)
|
||||
break;
|
||||
days -= daysPerMonth;
|
||||
}
|
||||
_dayOfMonth = days + 1;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // __RTCDATETIME_H__
|
153
firmware/lib/Rtc-master/src/RtcTemperature.h
Normal file
153
firmware/lib/Rtc-master/src/RtcTemperature.h
Normal file
@ -0,0 +1,153 @@
|
||||
|
||||
|
||||
#ifndef __RTCTEMPERATURE_H__
|
||||
#define __RTCTEMPERATURE_H__
|
||||
|
||||
|
||||
class RtcTemperature
|
||||
{
|
||||
public:
|
||||
// Constructor
|
||||
// a) Merge RTC registers into signed scaled temperature (x256),
|
||||
// then bind to RTC resolution.
|
||||
// | r11h | DP | r12h |
|
||||
// Bit: 15 14 13 12 11 10 9 8 . 7 6 5 4 3 2 1 0 -1 -2
|
||||
// s i i i i i i i . f f 0 0 0 0 0 0
|
||||
//
|
||||
// b) Rescale to (x4) by right-shifting (6) bits
|
||||
// | | DP | |
|
||||
// Bit: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 . 1 0 -1 -2
|
||||
// s s s s s s s i i i i i i i f f 0 0
|
||||
RtcTemperature(int8_t highByteDegreesC, uint8_t lowByteDegreesC)
|
||||
{
|
||||
int16_t scaledDegC = ((highByteDegreesC << 8) | (lowByteDegreesC & 0xC0)) >> 6;
|
||||
_centiDegC = scaledDegC * 100 / 4;
|
||||
}
|
||||
|
||||
RtcTemperature(int16_t centiDegC = 0) :
|
||||
_centiDegC(centiDegC)
|
||||
{
|
||||
}
|
||||
|
||||
// Float temperature Celsius
|
||||
float AsFloatDegC()
|
||||
{
|
||||
return (float)_centiDegC / 100.0f;
|
||||
}
|
||||
|
||||
// Float temperature Fahrenheit
|
||||
float AsFloatDegF()
|
||||
{
|
||||
return AsFloatDegC() * 1.8f + 32.0f;
|
||||
}
|
||||
|
||||
// centi degrees (1/100th of a degree),
|
||||
int16_t AsCentiDegC()
|
||||
{
|
||||
return _centiDegC;
|
||||
}
|
||||
|
||||
void Print(Stream& target, uint8_t decimals = 2, char decimal = '.')
|
||||
{
|
||||
int16_t decimalDivisor = 1;
|
||||
int16_t integerPart;
|
||||
int16_t decimalPart;
|
||||
|
||||
{
|
||||
int16_t rounded = abs(_centiDegC);
|
||||
// round up as needed
|
||||
if (decimals == 0)
|
||||
{
|
||||
rounded += 50;
|
||||
}
|
||||
else if (decimals == 1)
|
||||
{
|
||||
rounded += 5;
|
||||
decimalDivisor = 10;
|
||||
}
|
||||
|
||||
integerPart = rounded / 100;
|
||||
decimalPart = (rounded % 100) / decimalDivisor;
|
||||
}
|
||||
|
||||
// test for zero before printing negative sign to not print-0.00
|
||||
if (_centiDegC < 0 && (integerPart != 0 || decimalPart != 0))
|
||||
{
|
||||
target.print('-');
|
||||
}
|
||||
|
||||
// print integer part
|
||||
target.print(integerPart);
|
||||
|
||||
// print decimal part
|
||||
if (decimals != 0)
|
||||
{
|
||||
target.print(decimal);
|
||||
|
||||
if (decimalPart != 0)
|
||||
{
|
||||
target.print(decimalPart);
|
||||
}
|
||||
else
|
||||
{
|
||||
// append zeros as requested
|
||||
while (decimals > 0)
|
||||
{
|
||||
target.print('0');
|
||||
decimals--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const RtcTemperature& other) const
|
||||
{
|
||||
return (_centiDegC == other._centiDegC);
|
||||
};
|
||||
|
||||
bool operator>(const RtcTemperature& other) const
|
||||
{
|
||||
return (_centiDegC > other._centiDegC);
|
||||
};
|
||||
|
||||
bool operator<(const RtcTemperature& other) const
|
||||
{
|
||||
return (_centiDegC < other._centiDegC);
|
||||
};
|
||||
|
||||
bool operator>=(const RtcTemperature& other) const
|
||||
{
|
||||
return (_centiDegC >= other._centiDegC);
|
||||
};
|
||||
|
||||
bool operator<=(const RtcTemperature& other) const
|
||||
{
|
||||
return (_centiDegC <= other._centiDegC);
|
||||
};
|
||||
|
||||
bool operator!=(const RtcTemperature& other) const
|
||||
{
|
||||
return (_centiDegC != other._centiDegC);
|
||||
};
|
||||
|
||||
RtcTemperature operator-(const RtcTemperature& right)
|
||||
{
|
||||
RtcTemperature result;
|
||||
|
||||
result._centiDegC = (_centiDegC - right._centiDegC);
|
||||
return result;
|
||||
}
|
||||
|
||||
RtcTemperature operator+(const RtcTemperature& right)
|
||||
{
|
||||
RtcTemperature result;
|
||||
|
||||
result._centiDegC = (_centiDegC + right._centiDegC);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected:
|
||||
int16_t _centiDegC; // 1/100th of a degree temperature (100 x degC)
|
||||
};
|
||||
|
||||
#endif // __RTCTEMPERATURE_H__
|
34
firmware/lib/Rtc-master/src/RtcUtility.cpp
Normal file
34
firmware/lib/Rtc-master/src/RtcUtility.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "RtcUtility.h"
|
||||
|
||||
uint8_t BcdToUint8(uint8_t val)
|
||||
{
|
||||
return val - 6 * (val >> 4);
|
||||
}
|
||||
|
||||
uint8_t Uint8ToBcd(uint8_t val)
|
||||
{
|
||||
return val + 6 * (val / 10);
|
||||
}
|
||||
|
||||
uint8_t BcdToBin24Hour(uint8_t bcdHour)
|
||||
{
|
||||
uint8_t hour;
|
||||
if (bcdHour & 0x40)
|
||||
{
|
||||
// 12 hour mode, convert to 24
|
||||
bool isPm = ((bcdHour & 0x20) != 0);
|
||||
|
||||
hour = BcdToUint8(bcdHour & 0x1f);
|
||||
if (isPm)
|
||||
{
|
||||
hour += 12;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hour = BcdToUint8(bcdHour);
|
||||
}
|
||||
return hour;
|
||||
}
|
19
firmware/lib/Rtc-master/src/RtcUtility.h
Normal file
19
firmware/lib/Rtc-master/src/RtcUtility.h
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
#ifndef __RTCUTILITY_H__
|
||||
#define __RTCUTILITY_H__
|
||||
|
||||
// ESP32 complains if not included
|
||||
#if defined(ARDUINO_ARCH_ESP32)
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
// for some reason, the DUE board support does not define this, even though other non AVR archs do
|
||||
#ifndef _BV
|
||||
#define _BV(b) (1UL << (b))
|
||||
#endif
|
||||
|
||||
extern uint8_t BcdToUint8(uint8_t val);
|
||||
extern uint8_t Uint8ToBcd(uint8_t val);
|
||||
extern uint8_t BcdToBin24Hour(uint8_t bcdHour);
|
||||
|
||||
#endif // __RTCUTILITY_H__
|
Reference in New Issue
Block a user