Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
24f4da3
Correct bug in timer example.
icaven Sep 23, 2016
22a0c5e
Correct bug in timer example.
icaven Sep 23, 2016
8bc5132
Modify type name.
icaven Jan 11, 2017
9c0134d
Discard the first analog measurement after the ADC is powered up.
icaven Jan 11, 2017
9e34dda
Implement default sleep and wake functions.
icaven Jan 11, 2017
bf53e65
Implement sleep and wake functions for the timer.
icaven Jan 11, 2017
f76e69f
Implement serial output for attiny84.
icaven Jan 11, 2017
27a7f34
Support sleep and wake functions for the serial port for atmega328p
icaven Jan 11, 2017
c9826eb
Change AbstractTimer to not depend on Arduino header.
icaven Jan 11, 2017
0499c7a
Documentation added; reset watchdog timer when enabling.
icaven Jan 11, 2017
42b7317
Change Timer interface to include sleep and wake functions.
icaven Jan 11, 2017
29c0602
Ignore some files used by PlatformIO
icaven Jan 11, 2017
d58d3f3
Add a PlatformIO library description file.
icaven Jan 11, 2017
9204605
Add PlatformIO configuration files.
icaven Jan 11, 2017
9f54136
Add the maintainer flag to the library manifest.
icaven Jan 11, 2017
708c8eb
Merge branch 'master' of /Users/icaven/Development/Libraries/jscrane/…
icaven Jan 11, 2017
0b08835
Merge changes with most recent pull from origin.
icaven Jan 11, 2017
fa0faf5
Merge changes with most recent pull from origin.
icaven Jan 11, 2017
a00cdc6
Ensure that the timer device is selected.
icaven Jan 11, 2017
71d5de2
Correct the url to the library.
icaven Jan 16, 2017
6302768
Merge branch 'master' into master
icaven Mar 17, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
.pioenvs
.clang_complete
.gcc-flags.json
*.bin
*.eep
*.elf
Expand All @@ -12,3 +15,4 @@ libcore.a
.clang_complete
.gcc-flags.json
.piolibdeps

22 changes: 22 additions & 0 deletions .library.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "Interrupted",
"authors":
[
{
"name": "Stephen Crane",
"email": "jscrane@gmail.com",
"url": "https://www.linkedin.com/in/jscrane",
"maintainer": true
}
],
"version" : "1.1.0",
"description" : "Interrupt driven device framework",
"keywords" : "avr, Arduino",
"repository":
{
"type" : "git",
"url": "https://github.com/jscrane/Interrupted.git"
},
"frameworks": ["arduino"],
"platforms": ["atmelavr"]
}
65 changes: 65 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Continuous Integration (CI) is the practice, in software
# engineering, of merging all developer working copies with a shared mainline
# several times a day < http://docs.platformio.org/en/stable/ci/index.html >
#
# Documentation:
#
# * Travis CI Embedded Builds with PlatformIO
# < https://docs.travis-ci.com/user/integration/platformio/ >
#
# * PlatformIO integration with Travis CI
# < http://docs.platformio.org/en/stable/ci/travis.html >
#
# * User Guide for `platformio ci` command
# < http://docs.platformio.org/en/stable/userguide/cmd_ci.html >
#
#
# Please choice one of the following templates (proposed below) and uncomment
# it (remove "# " before each line) or use own configuration according to the
# Travis CI documentation (see above).
#


#
# Template #1: General project. Test it using existing `platformio.ini`.
#

# language: python
# python:
# - "2.7"
#
# sudo: false
# cache:
# directories:
# - "~/.platformio"
#
# install:
# - pip install -U platformio
#
# script:
# - platformio run


#
# Template #2: The project is intended to by used as a library with examples
#

# language: python
# python:
# - "2.7"
#
# sudo: false
# cache:
# directories:
# - "~/.platformio"
#
# env:
# - PLATFORMIO_CI_SRC=path/to/test/file.c
# - PLATFORMIO_CI_SRC=examples/file.ino
# - PLATFORMIO_CI_SRC=path/to/test/directory
#
# install:
# - pip install -U platformio
#
# script:
# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N
15 changes: 13 additions & 2 deletions analog.h
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
#ifndef __ANALOG_H__
#define __ANALOG_H__

#include <Arduino.h>
#include "device.h"

/**
* Analog-to-Digital conversion.
*
*
* FIXME: analogReadResolution()
*/
class Analog: public Device {
public:
// pin is the analog input, e.g., A0-A7
Analog(int pin, unsigned ref = DEFAULT):
Device(pin), _pin(pin), _ref(ref) {}
Device(pin), _pin(pin), _ref(ref), _next_reading_valid(false) {}

// not enabled by default
bool begin();
Expand All @@ -24,6 +27,13 @@ class Analog: public Device {
// returns last converted value or 0xffff if not ready
unsigned read();

// call to turn off ADC altogether and back on again
virtual void sleep();
virtual void wake();

bool next_reading_valid(void) {return _next_reading_valid;}
void next_reading_will_be_valid() {_next_reading_valid = true; }

protected:
void _enable(bool enabled);

Expand All @@ -33,6 +43,7 @@ class Analog: public Device {

int _pin;
unsigned _ref;
volatile bool _next_reading_valid;
};

#endif
28 changes: 23 additions & 5 deletions atmega328p/analog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,22 @@
#include "device.h"
#include "analog.h"

static Device *adc;
static Analog *adc;
static volatile unsigned reading = 0xffff;

ISR(ADC_vect) {
if (adc) {
uint8_t low = ADCL;
uint8_t high = ADCH;
reading = (high << 8) | low;
adc->ready();
if (adc->_next_reading_valid)
adc->ready();
else
{
// Can't use this conversion so start a new conversion
ADCSRA |= bit(ADSC) | bit(ADIE);
adc->_next_reading_valid = true;
}
}
}

Expand All @@ -39,13 +46,24 @@ void Analog::_init() {
ADMUX = (_ref << 6) | ((_pin - A0) & 0x0f);
}

void Analog::sleep() {
ADCSRA &= ~_BV(ADEN);
ACSR |= _BV(ACD);
power_adc_disable();
}

void Analog::wake() {
power_adc_enable();
_next_reading_valid = false; // Ignore first reading after power on
ADCSRA |= _BV(ADEN);
ACSR &= ~_BV(ACD);
}

bool Analog::begin() {
adc = this;
unsigned sreg = SREG;
cli();
power_adc_enable();
ADCSRA |= _BV(ADEN);
ACSR &= ~_BV(ACD);
wake();
_init();
SREG = sreg;
return false;
Expand Down
15 changes: 14 additions & 1 deletion atmega328p/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

#include "device.h"

// Ensure that these are defined properly (there appears to be a bug in avr/power.h for ATMega328[P])
#define power_all_enable() (PRR &= (uint8_t)~((1<<PRADC)|(1<<PRTIM0)|(1<<PRTIM1)|(1<<PRTIM2)|(1<<PRSPI)|(1<<PRTWI)|(1<<PRUSART0)))
#define power_all_disable() (PRR |= (uint8_t)((1<<PRADC)|(1<<PRTIM0)|(1<<PRTIM1)|(1<<PRTIM2)|(1<<PRSPI)|(1<<PRTWI)|(1<<PRUSART0)))

void Devices::begin() {
// "...[it] is therefore required to turn off the watchdog
// early during program startup..." (from avr/wdt.h)
Expand All @@ -14,6 +18,9 @@ void Devices::begin() {
// turn off ADC and analog comparator
ADCSRA &= ~bit(ADEN);
ACSR |= bit(ACD);


// power down all modules until they are needed
power_all_disable();

// turn off the brown-out detector
Expand All @@ -23,7 +30,13 @@ void Devices::begin() {
digitalWrite(i, LOW);

for (int i = 0; i < _n; i++)
_devices[i]->enable(_devices[i]->begin());
{
if (_devices[i]->begin())
{
_devices[i]->wake();
_devices[i]->enable(true);
}
}

sei();
}
Expand Down
26 changes: 20 additions & 6 deletions atmega328p/serial.cpp
Original file line number Diff line number Diff line change
@@ -1,24 +1,38 @@
#include <avr/io.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <Arduino.h>

#include "device.h"
#include "serial.h"

void SerialDevice::init() {
if (_baud) {
power_usart0_enable();
unsigned prescale = ((F_CPU) / 16 + (_baud / 2)) / _baud - 1;
uint8_t sreg = SREG;
cli();

uint8_t saved_SREG = SREG; // Save the interrupt flag
cli(); // disable interrupts while initializing the USART
UBRR0H = (prescale >> 8) & 0xff;
UBRR0L = prescale & 0xff;
UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); // 8N1
SREG = sreg;
UCSR0C = bit(UCSZ00) | bit(UCSZ01); // 8 bits, no parity, 1 stop bit
SREG = saved_SREG; // restore the interrupt flag
}
}

unsigned SerialDevice::_sleepmode() {
return SLEEP_MODE_IDLE;
}

// call to turn off device altogether
void SerialDevice::sleep()
{
power_usart0_disable(); // Power down the USART
}

// call to turn device on again
void SerialDevice::wake()
{
power_usart0_enable(); // Ensure USART powered up
this->init(); // After power on, the module must be initialized
}
3 changes: 2 additions & 1 deletion atmega328p/serialin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ static SerialIn *device;

bool SerialIn::begin() {
device = this;
init();
wake();
sleep();
return true;
}

Expand Down
8 changes: 7 additions & 1 deletion atmega328p/serialout.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <avr/io.h>
#include <avr/power.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <Arduino.h>
Expand All @@ -11,8 +12,9 @@ static SerialOut *device;

bool SerialOut::begin() {
device = this;
init();
wake();
UCSR0B |= _BV(TXEN0);
sleep();
return false;
}

Expand All @@ -30,10 +32,13 @@ bool SerialOut::write(char const *ptr) {
return false;
}

// Output a single character; may be called from interrupt service routine
// If no more characters, then signal that the device is ready
void SerialOut::do_output() {
byte b = *_tx_ptr;
if (b) {
_tx_ptr++;
bitClear(UCSR0B, TXC0);
UDR0 = b;
} else {
_tx_ptr = 0;
Expand All @@ -47,3 +52,4 @@ ISR(USART_TX_vect)
if (device)
device->do_output();
}

29 changes: 27 additions & 2 deletions atmega328p/timer.cpp
Original file line number Diff line number Diff line change
@@ -1,27 +1,52 @@
#include <avr/io.h>
#include <avr/power.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/interrupt.h>

#include "device.h"
#include "timer.h"

// Timer 1 is used so as to avoid conflict with the timer 0, used by the delay() function in the Arduino library
static Device *t1;

// Ensure that these are defined properly
#ifndef power_timer1_enable
#define power_timer1_enable() (PRR &= (uint8_t)~(1 << PRTIM1))
#endif
#ifndef power_timer1_disable
#define power_timer1_disable() (PRR |= (uint8_t)(1 << PRTIM1))
#endif

ISR(TIMER1_COMPA_vect) {
if (t1)
t1->ready();
}

// call to turn off device altogether
void Timer::sleep()
{
power_timer1_disable();
}

// call to turn device on again
void Timer::wake()
{
power_timer1_enable();
}


bool Timer::begin() {
t1 = this;

power_timer1_enable();

TCCR1A = 0;
// CTC mode, 1024 prescaler
TCCR1B = _BV(WGM12) | _BV(CS10) | _BV(CS12);

OCR1A = F_CPU / 1024000 - 1; // 1 ms
OCR1A = (uint16_t) (F_CPU / 1024000L) - 1; // approximately 1 ms divided by the divisor
sleep();
return false;
}

Expand All @@ -34,9 +59,9 @@ void Timer::_enable(bool e) {
else
TIMSK1 &= ~_BV(OCIE1A);
SREG = sreg;

}

unsigned Timer::_sleepmode() {
return SLEEP_MODE_IDLE;
}

2 changes: 1 addition & 1 deletion atmega328p/watchdog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ void Watchdog::_enable(bool e) {
cli();
uint8_t b = 0;
if (e) {
wdt_reset();
wdt_reset(); // Ensure that the timer will start from 0 again
b = _BV(WDIE) | _scale;
}
WDTCSR = _BV(WDCE) | _BV(WDE);
Expand Down
Loading