Adding Servo library (ServoTimer1 from the playground) by Jim Studt.
This commit is contained in:
parent
4b2b39e383
commit
d98fdd989f
|
@ -0,0 +1,125 @@
|
|||
#include <Servo.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
/*
|
||||
Servo.h - Hardware Servo Timer Library
|
||||
Author: Jim Studt, jim@federated.com
|
||||
Copyright (c) 2007 David A. Mellis. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
uint8_t Servo::attached9 = 0;
|
||||
uint8_t Servo::attached10 = 0;
|
||||
|
||||
void Servo::seizeTimer1()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
|
||||
cli();
|
||||
TCCR1A = _BV(WGM11); /* Fast PWM, ICR1 is top */
|
||||
TCCR1B = _BV(WGM13) | _BV(WGM12) /* Fast PWM, ICR1 is top */
|
||||
| _BV(CS11) /* div 8 clock prescaler */
|
||||
;
|
||||
OCR1A = 3000;
|
||||
OCR1B = 3000;
|
||||
ICR1 = clockCyclesPerMicrosecond()*(20000L/8); // 20000 uS is a bit fast for the refresh, 20ms, but
|
||||
// it keeps us from overflowing ICR1 at 20MHz clocks
|
||||
// That "/8" at the end is the prescaler.
|
||||
#if defined(__AVR_ATmega168__)
|
||||
TIMSK1 &= ~(_BV(OCIE1A) | _BV(OCIE1B) | _BV(TOIE1) );
|
||||
#else
|
||||
TIMSK &= ~(_BV(TICIE1) | _BV(OCIE1A) | _BV(OCIE1B) | _BV(TOIE1) );
|
||||
#endif
|
||||
|
||||
SREG = oldSREG; // undo cli()
|
||||
}
|
||||
|
||||
void Servo::releaseTimer1() {}
|
||||
|
||||
#define NO_ANGLE (0xff)
|
||||
|
||||
Servo::Servo() : pin(0), angle(NO_ANGLE), min16(34), max16(150) {}
|
||||
Servo::Servo(int min, int max) : pin(0), angle(NO_ANGLE), min16(min / 16), max16(max / 16) {}
|
||||
|
||||
uint8_t Servo::attach(int pinArg)
|
||||
{
|
||||
if (pinArg != 9 && pinArg != 10) return 0;
|
||||
|
||||
pin = pinArg;
|
||||
angle = NO_ANGLE;
|
||||
digitalWrite(pin, LOW);
|
||||
pinMode(pin, OUTPUT);
|
||||
|
||||
if (!attached9 && !attached10) seizeTimer1();
|
||||
|
||||
if (pin == 9) {
|
||||
attached9 = 1;
|
||||
TCCR1A = TCCR1A & ~_BV(COM1A0) | _BV(COM1A1);
|
||||
}
|
||||
|
||||
if (pin == 10) {
|
||||
attached10 = 1;
|
||||
TCCR1A = TCCR1A & ~_BV(COM1B0) | _BV(COM1B1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Servo::detach()
|
||||
{
|
||||
// muck with timer flags
|
||||
if (pin == 9) {
|
||||
attached9 = 0;
|
||||
TCCR1A = TCCR1A & ~_BV(COM1A0) & ~_BV(COM1A1);
|
||||
pinMode(pin, INPUT);
|
||||
}
|
||||
|
||||
if (pin == 10) {
|
||||
attached10 = 0;
|
||||
TCCR1A = TCCR1A & ~_BV(COM1B0) & ~_BV(COM1B1);
|
||||
pinMode(pin, INPUT);
|
||||
}
|
||||
|
||||
if (!attached9 && !attached10) releaseTimer1();
|
||||
}
|
||||
|
||||
void Servo::write(int angleArg)
|
||||
{
|
||||
uint16_t p;
|
||||
|
||||
if (angleArg < 0) angleArg = 0;
|
||||
if (angleArg > 180) angleArg = 180;
|
||||
angle = angleArg;
|
||||
|
||||
// bleh, have to use longs to prevent overflow, could be tricky if always a 16MHz clock, but not true
|
||||
// That 8L on the end is the TCNT1 prescaler, it will need to change if the clock's prescaler changes,
|
||||
// but then there will likely be an overflow problem, so it will have to be handled by a human.
|
||||
p = (min16*16L*clockCyclesPerMicrosecond() + (max16-min16)*(16L*clockCyclesPerMicrosecond())*angle/180L)/8L;
|
||||
if (pin == 9) OCR1A = p;
|
||||
if (pin == 10) OCR1B = p;
|
||||
}
|
||||
|
||||
uint8_t Servo::read()
|
||||
{
|
||||
return angle;
|
||||
}
|
||||
|
||||
uint8_t Servo::attached()
|
||||
{
|
||||
if (pin == 9 && attached9) return 1;
|
||||
if (pin == 10 && attached10) return 1;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
#ifndef Servo_h
|
||||
#define Servo_h
|
||||
|
||||
/*
|
||||
Servo.h - Hardware Servo Timer Library
|
||||
Author: Jim Studt, jim@federated.com
|
||||
Copyright (c) 2007 David A. Mellis. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <wiring.h>
|
||||
|
||||
class Servo
|
||||
{
|
||||
private:
|
||||
uint8_t pin;
|
||||
uint8_t angle; // in degrees
|
||||
uint8_t min16; // minimum pulse, 16uS units (default is 34)
|
||||
uint8_t max16; // maximum pulse, 16uS units, 0-4ms range (default is 150)
|
||||
static void seizeTimer1();
|
||||
static void releaseTimer1();
|
||||
static uint8_t attached9;
|
||||
static uint8_t attached10;
|
||||
public:
|
||||
Servo();
|
||||
Servo(int, int); // pulse length for 0 degrees in microseconds, 540uS default
|
||||
// pulse length for 180 degrees in microseconds, 2400uS default
|
||||
uint8_t attach(int); // attach to a pin, sets pinMode, returns 0 on failure, won't
|
||||
// position the servo until a subsequent write() happens
|
||||
// Only works for 9 and 10.
|
||||
void detach();
|
||||
void write(int); // specify the angle in degrees, 0 to 180
|
||||
uint8_t read();
|
||||
uint8_t attached();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,22 @@
|
|||
#######################################
|
||||
# Syntax Coloring Map Servo
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
Servo KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
attach KEYWORD2
|
||||
detach KEYWORD2
|
||||
write KEYWORD2
|
||||
read KEYWORD2
|
||||
attached KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
Loading…
Reference in New Issue