221 lines
5.4 KiB
C++
221 lines
5.4 KiB
C++
/**
|
|
* The MySensors Arduino library handles the wireless radio link and protocol
|
|
* between your home built sensors/actuators and HA controller of choice.
|
|
* The sensors forms a self healing radio network with optional repeaters. Each
|
|
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
|
* network topology allowing messages to be routed to nodes.
|
|
*
|
|
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
|
* Copyright (C) 2013-2015 Sensnology AB
|
|
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
|
*
|
|
* Documentation: http://www.mysensors.org
|
|
* Support Forum: http://forum.mysensors.org
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* version 2 as published by the Free Software Foundation.
|
|
*/
|
|
|
|
#ifdef ARDUINO_ARCH_AVR
|
|
|
|
#include "MyHw.h"
|
|
#include "MyHwATMega328.h"
|
|
|
|
int8_t pinIntTrigger = 0;
|
|
void wakeUp() //place to send the interrupts
|
|
{
|
|
pinIntTrigger = 1;
|
|
}
|
|
void wakeUp2() //place to send the second interrupts
|
|
{
|
|
pinIntTrigger = 2;
|
|
}
|
|
|
|
// Watchdog Timer interrupt service routine. This routine is required
|
|
// to allow automatic WDIF and WDIE bit clearance in hardware.
|
|
ISR (WDT_vect)
|
|
{
|
|
// WDIE & WDIF is cleared in hardware upon entering this ISR
|
|
wdt_disable();
|
|
}
|
|
|
|
MyHwATMega328::MyHwATMega328() : MyHw()
|
|
{
|
|
}
|
|
|
|
|
|
/*
|
|
|
|
// The following was redifined as macros to save space
|
|
|
|
inline uint8_t MyHwATMega328::readConfig(uint8_t pos) {
|
|
return eeprom_read_byte((uint8_t*)pos);
|
|
}
|
|
|
|
inline void MyHwATMega328::writeConfig(uint8_t pos, uint8_t value) {
|
|
eeprom_update_byte((uint8_t*)pos, value);
|
|
}
|
|
|
|
inline void MyHwATMega328::readConfigBlock(void* buf, void * pos, size_t length) {
|
|
eeprom_read_block(buf, (void*)pos, length);
|
|
}
|
|
|
|
inline void MyHwATMega328::writeConfigBlock(void* pos, void* buf, size_t length) {
|
|
eeprom_write_block((void*)pos, (void*)buf, length);
|
|
}
|
|
|
|
|
|
inline void MyHwATMega328::init() {
|
|
Serial.begin(BAUD_RATE);
|
|
}
|
|
|
|
inline void MyHwATMega328::watchdogReset() {
|
|
wdt_reset();
|
|
}
|
|
|
|
inline void MyHwATMega328::reboot() {
|
|
wdt_enable(WDTO_15MS); for (;;);
|
|
}
|
|
|
|
inline unsigned long MyHwATMega328::millis() {
|
|
return ::millis();
|
|
}
|
|
*/
|
|
|
|
|
|
void powerDown(period_t period) {
|
|
|
|
ADCSRA &= ~(1 << ADEN);
|
|
|
|
if (period != SLEEP_FOREVER)
|
|
{
|
|
wdt_enable(period);
|
|
WDTCSR |= (1 << WDIE);
|
|
}
|
|
#if defined __AVR_ATmega328P__
|
|
do {
|
|
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
|
|
cli();
|
|
sleep_enable();
|
|
sleep_bod_disable();
|
|
sei();
|
|
sleep_cpu();
|
|
sleep_disable();
|
|
sei();
|
|
} while (0);
|
|
#else
|
|
do {
|
|
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
|
|
cli();
|
|
sleep_enable();
|
|
sei();
|
|
sleep_cpu();
|
|
sleep_disable();
|
|
sei();
|
|
} while (0);
|
|
#endif
|
|
|
|
ADCSRA |= (1 << ADEN);
|
|
}
|
|
|
|
void MyHwATMega328::internalSleep(unsigned long ms) {
|
|
// Let serial prints finish (debug, log etc)
|
|
#ifdef ENABLED_SERIAL
|
|
Serial.flush();
|
|
#endif
|
|
pinIntTrigger = 0;
|
|
while (!pinIntTrigger && ms >= 8000) { powerDown(SLEEP_8S); ms -= 8000; }
|
|
if (!pinIntTrigger && ms >= 4000) { powerDown(SLEEP_4S); ms -= 4000; }
|
|
if (!pinIntTrigger && ms >= 2000) { powerDown(SLEEP_2S); ms -= 2000; }
|
|
if (!pinIntTrigger && ms >= 1000) { powerDown(SLEEP_1S); ms -= 1000; }
|
|
if (!pinIntTrigger && ms >= 500) { powerDown(SLEEP_500MS); ms -= 500; }
|
|
if (!pinIntTrigger && ms >= 250) { powerDown(SLEEP_250MS); ms -= 250; }
|
|
if (!pinIntTrigger && ms >= 125) { powerDown(SLEEP_120MS); ms -= 120; }
|
|
if (!pinIntTrigger && ms >= 64) { powerDown(SLEEP_60MS); ms -= 60; }
|
|
if (!pinIntTrigger && ms >= 32) { powerDown(SLEEP_30MS); ms -= 30; }
|
|
if (!pinIntTrigger && ms >= 16) { powerDown(SLEEP_15Ms); ms -= 15; }
|
|
}
|
|
|
|
void MyHwATMega328::sleep(unsigned long ms) {
|
|
internalSleep(ms);
|
|
}
|
|
|
|
bool MyHwATMega328::sleep(uint8_t interrupt, uint8_t mode, unsigned long ms) {
|
|
// Let serial prints finish (debug, log etc)
|
|
bool pinTriggeredWakeup = true;
|
|
attachInterrupt(interrupt, wakeUp, mode);
|
|
if (ms>0) {
|
|
pinIntTrigger = 0;
|
|
internalSleep(ms);
|
|
if (0 == pinIntTrigger) {
|
|
pinTriggeredWakeup = false;
|
|
}
|
|
} else {
|
|
#ifdef ENABLED_SERIAL
|
|
Serial.flush();
|
|
#endif
|
|
powerDown(SLEEP_FOREVER);
|
|
}
|
|
detachInterrupt(interrupt);
|
|
return pinTriggeredWakeup;
|
|
}
|
|
|
|
inline uint8_t MyHwATMega328::sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) {
|
|
int8_t retVal = 1;
|
|
attachInterrupt(interrupt1, wakeUp, mode1);
|
|
attachInterrupt(interrupt2, wakeUp2, mode2);
|
|
if (ms>0) {
|
|
pinIntTrigger = 0;
|
|
internalSleep(ms);
|
|
if (0 == pinIntTrigger) {
|
|
retVal = -1;
|
|
}
|
|
} else {
|
|
#ifdef ENABLED_SERIAL
|
|
Serial.flush();
|
|
#endif
|
|
powerDown(SLEEP_FOREVER);
|
|
}
|
|
detachInterrupt(interrupt1);
|
|
detachInterrupt(interrupt2);
|
|
|
|
if (1 == pinIntTrigger) {
|
|
retVal = (int8_t)interrupt1;
|
|
} else if (2 == pinIntTrigger) {
|
|
retVal = (int8_t)interrupt2;
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
void MyHwATMega328::debugPrint(bool isGW, const char *fmt, ... ) {
|
|
char fmtBuffer[300];
|
|
if (isGW) {
|
|
// prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE)
|
|
snprintf_P(fmtBuffer, 299, PSTR("0;0;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE);
|
|
Serial.print(fmtBuffer);
|
|
}
|
|
va_list args;
|
|
va_start (args, fmt );
|
|
va_end (args);
|
|
if (isGW) {
|
|
// Truncate message if this is gateway node
|
|
vsnprintf_P(fmtBuffer, 60, fmt, args);
|
|
fmtBuffer[59] = '\n';
|
|
fmtBuffer[60] = '\0';
|
|
} else {
|
|
vsnprintf_P(fmtBuffer, 299, fmt, args);
|
|
}
|
|
va_end (args);
|
|
Serial.print(fmtBuffer);
|
|
Serial.flush();
|
|
|
|
//Serial.write(freeRam());
|
|
}
|
|
#endif
|
|
|
|
#endif // #ifdef ARDUINO_ARCH_AVR
|