00001 /* Copyright (c) 2009 by Alex Leone <acleone ~AT~ gmail.com> 00002 00003 This file is part of the Arduino TLC5940 Library. 00004 00005 The Arduino TLC5940 Library is free software: you can redistribute it 00006 and/or modify it under the terms of the GNU General Public License as 00007 published by the Free Software Foundation, either version 3 of the 00008 License, or (at your option) any later version. 00009 00010 The Arduino TLC5940 Library is distributed in the hope that it will be 00011 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with The Arduino TLC5940 Library. If not, see 00017 <http://www.gnu.org/licenses/>. */ 00018 00019 #ifndef TLC_SERVOS_H 00020 #define TLC_SERVOS_H 00021 00025 #include <avr/io.h> 00026 #include "Tlc5940.h" 00027 00028 #ifndef SERVO_MAX_ANGLE 00029 00030 #define SERVO_MAX_ANGLE 180 00031 #endif 00032 #ifndef SERVO_MIN_WIDTH 00033 00034 #define SERVO_MIN_WIDTH 204 00035 #endif 00036 #ifndef SERVO_MAX_WIDTH 00037 00038 #define SERVO_MAX_WIDTH 410 00039 #endif 00040 #ifndef SERVO_TIMER1_TOP 00041 00045 #define SERVO_TIMER1_TOP 20000 00046 #endif 00047 #ifndef SERVO_TIMER2_TOP 00048 00052 #define SERVO_TIMER2_TOP 77 00053 #endif 00054 00055 void tlc_initServos(uint8_t initAngle = 0); 00056 void tlc_setServo(TLC_CHANNEL_TYPE channel, uint8_t angle); 00057 uint8_t tlc_getServo(TLC_CHANNEL_TYPE channel); 00058 uint16_t tlc_angleToVal(uint8_t angle); 00059 uint8_t tlc_valToAngle(uint16_t value); 00060 00069 /* @{ */ 00070 00074 void tlc_initServos(uint8_t initAngle) 00075 { 00076 Tlc.init(tlc_angleToVal(initAngle)); 00077 TCCR1B &= ~(_BV(CS12) | _BV(CS11) | _BV(CS10)); // stop timer1 00078 ICR1 = SERVO_TIMER1_TOP; 00079 TCNT1 = 0; 00080 #ifdef TLC_ATMEGA_8_H 00081 uint8_t oldTCCR2 = TCCR2; 00082 TCCR2 = 0; 00083 TCNT2 = 0; 00084 OCR2 = SERVO_TIMER2_TOP / 2; 00085 TCCR2 = oldTCCR2; 00086 #else 00087 uint8_t oldTCCR2B = TCCR2B; 00088 TCCR2B = 0; 00089 TCNT2 = 0; 00090 OCR2A = SERVO_TIMER2_TOP; 00091 TCCR2B = oldTCCR2B; 00092 #endif 00093 TCCR1B |= _BV(CS11); // start timer1 with div 8 prescale 00094 } 00095 00099 void tlc_setServo(TLC_CHANNEL_TYPE channel, uint8_t angle) 00100 { 00101 Tlc.set(channel, tlc_angleToVal(angle)); 00102 } 00103 00106 uint8_t tlc_getServo(TLC_CHANNEL_TYPE channel) 00107 { 00108 return tlc_valToAngle(Tlc.get(channel)); 00109 } 00110 00113 uint16_t tlc_angleToVal(uint8_t angle) 00114 { 00115 return 4095 - SERVO_MIN_WIDTH - ( 00116 ((uint16_t)(angle) * (uint16_t)(SERVO_MAX_WIDTH - SERVO_MIN_WIDTH)) 00117 / SERVO_MAX_ANGLE); 00118 } 00119 00122 uint8_t tlc_valToAngle(uint16_t value) 00123 { 00124 return SERVO_MAX_ANGLE * (4095 - SERVO_MIN_WIDTH - value) 00125 / (SERVO_MAX_WIDTH - SERVO_MIN_WIDTH); 00126 } 00127 00128 /* @} */ 00129 00130 #endif 00131